ZQuest Classic Coverage Report


Directory: src/
File: src/zq/zq_tiles.cpp
Date: 2024-09-10 05:08:14
Exec Total Coverage
Lines: 98 7702 1.3%
Functions: 1 199 0.5%
Branches: 14 6713 0.2%

Line Branch Exec Source
1 #include <cstring>
2 #include <cmath>
3
4 #include "base/files.h"
5 #include "base/qrs.h"
6 #include "base/dmap.h"
7 #include "base/cpool.h"
8 #include "base/autocombo.h"
9 #include "base/packfile.h"
10 #include "base/gui.h"
11 #include "base/combo.h"
12 #include "base/msgstr.h"
13 #include "base/zdefs.h"
14 #include "new_subscr.h"
15 #include "subscr.h"
16 #include "zq/zquestdat.h"
17 #include "zq/zq_tiles.h"
18 #include "zq/zquest.h"
19 #include "tiles.h"
20 #include "zq/zq_misc.h"
21 #include "zq/zq_class.h"
22 #include "base/zsys.h"
23 #include "base/colors.h"
24 #include "base/qst.h"
25 #include "gui/jwin.h"
26 #include <base/new_menu.h>
27 #include "base/jwinfsel.h"
28 #include "zc/zc_custom.h"
29 #include "zq/questReport.h"
30 #include "dialog/info.h"
31 #include "dialog/scaletile.h"
32 #include "dialog/rotatetile.h"
33 #include "dialog/alert.h"
34 #include "drawing.h"
35 #include "colorname.h"
36 #include "zq/render.h"
37 #include "zinfo.h"
38 #include <fmt/format.h>
39 #include <functional>
40 #include "zq/moveinfo.h"
41 using std::set;
42
43 extern zcmodule moduledata;
44
45 #ifdef _MSC_VER
46 #define stricmp _stricmp
47 #endif
48
49 #define HIDE_USED (show_only_unused_tiles&1)
50 #define HIDE_UNUSED (show_only_unused_tiles&2)
51 #define HIDE_BLANK (show_only_unused_tiles&4)
52 #define HIDE_8BIT_MARKER (show_only_unused_tiles&8)
53
54 extern void large_dialog(DIALOG *d);
55 static void massRecolorReset4Bit();
56 static void massRecolorReset8Bit();
57 static bool massRecolorSetup(int32_t cset);
58 static void massRecolorApply(int32_t tile);
59 extern int32_t last_droplist_sel;
60 extern int32_t TilePgCursorCol, CmbPgCursorCol;
61
62 int32_t ex=0;
63 int32_t nextcombo_fake_click=0;
64 int32_t invcol=0;
65 int32_t tthighlight = 1;
66 int32_t showcolortip = 1;
67 int32_t show_quartgrid = 0, hide_grid = 0;
68
69 tiledata *newundotilebuf;
70 std::vector<newcombo> undocombobuf;
71
72 BITMAP *selection_pattern;
73 byte selection_grid[18][18];
74 byte selection_anchor=0;
75
76 enum {selection_mode_normal, selection_mode_add, selection_mode_subtract, selection_mode_exclude};
77 BITMAP *selecting_pattern;
78 int32_t selecting_x1, selecting_x2, selecting_y1, selecting_y2;
79
80 extern int32_t bidcomboscripts_cnt;
81 extern script_struct bidcomboscripts[NUMSCRIPTSCOMBODATA];
82
83 BITMAP *intersection_pattern;
84
85 byte relational_template[48][4]=
86 {
87 { 0, 0, 0, 0 },
88 { 0, 1, 0, 0 },
89 { 1, 0, 0, 0 },
90 { 1, 1, 0, 0 },
91 { 0, 0, 1, 0 },
92 { 0, 1, 1, 0 },
93 { 1, 0, 1, 0 },
94 { 1, 1, 1, 0 },
95 { 0, 0, 0, 1 },
96 { 0, 1, 0, 1 },
97 { 1, 0, 0, 1 },
98 { 1, 1, 0, 1 },
99 { 0, 0, 1, 1 },
100 { 0, 1, 1, 1 },
101 { 1, 0, 1, 1 },
102 { 1, 1, 1, 1 },
103 { 0, 2, 0, 2 },
104 { 1, 2, 0, 2 },
105 { 0, 2, 1, 2 },
106 { 1, 2, 1, 2 },
107 { 3, 3, 0, 0 },
108 { 3, 3, 1, 0 },
109 { 3, 3, 0, 1 },
110 { 3, 3, 1, 1 },
111 { 3, 4, 0, 2 },
112 { 3, 4, 1, 2 },
113 { 2, 0, 2, 0 },
114 { 2, 1, 2, 0 },
115 { 2, 0, 2, 1 },
116 { 2, 1, 2, 1 },
117 { 2, 2, 2, 2 },
118 { 4, 3, 2, 0 },
119 { 4, 3, 2, 1 },
120 { 4, 4, 2, 2 },
121 { 0, 0, 3, 3 },
122 { 0, 1, 3, 3 },
123 { 1, 0, 3, 3 },
124 { 1, 1, 3, 3 },
125 { 0, 2, 3, 4 },
126 { 1, 2, 3, 4 },
127 { 3, 3, 3, 3 },
128 { 3, 4, 3, 4 },
129 { 2, 0, 4, 3 },
130 { 2, 1, 4, 3 },
131 { 2, 2, 4, 4 },
132 { 4, 3, 4, 3 },
133 { 4, 4, 4, 4 },
134 { 5, 5, 5, 5 }
135 };
136
137 byte dungeon_carving_template[96][4]=
138 {
139 { 0, 0, 0, 0 },
140 { 0, 1, 0, 0 },
141 { 1, 0, 0, 0 },
142 { 1, 1, 0, 0 },
143 { 0, 0, 1, 0 },
144 { 0, 1, 1, 0 },
145 { 1, 0, 1, 0 },
146 { 1, 1, 1, 0 },
147 { 0, 0, 0, 1 },
148 { 0, 1, 0, 1 },
149 { 1, 0, 0, 1 },
150 { 1, 1, 0, 1 },
151 { 0, 0, 1, 1 },
152 { 0, 1, 1, 1 },
153 { 1, 0, 1, 1 },
154 { 1, 1, 1, 1 },
155 { 0, 2, 0, 2 },
156 { 1, 2, 0, 2 },
157 { 0, 2, 1, 2 },
158 { 1, 2, 1, 2 },
159 { 3, 3, 0, 0 },
160 { 3, 3, 1, 0 },
161 { 3, 3, 0, 1 },
162 { 3, 3, 1, 1 },
163 { 3, 4, 0, 2 },
164 { 3, 4, 1, 2 },
165 { 2, 0, 2, 0 },
166 { 2, 1, 2, 0 },
167 { 2, 0, 2, 1 },
168 { 2, 1, 2, 1 },
169 { 2, 2, 2, 2 },
170 { 4, 3, 2, 0 },
171 { 4, 3, 2, 1 },
172 { 4, 4, 2, 2 },
173 { 0, 0, 3, 3 },
174 { 0, 1, 3, 3 },
175 { 1, 0, 3, 3 },
176 { 1, 1, 3, 3 },
177 { 0, 2, 3, 4 },
178 { 1, 2, 3, 4 },
179 { 3, 3, 3, 3 },
180 { 3, 4, 3, 4 },
181 { 2, 0, 4, 3 },
182 { 2, 1, 4, 3 },
183 { 2, 2, 4, 4 },
184 { 4, 3, 4, 3 },
185 { 4, 4, 4, 4 },
186 { 5, 5, 5, 5 },
187
188 { 5, 5, 5, 5 },
189 { 6, 6, 6, 6 },
190 { 7, 7, 7, 7 },
191 { 7, 6, 7, 6 },
192 { 8, 8, 8, 8 },
193 { 16, 6, 8, 15 },
194 { 7, 7, 8, 8 },
195 { 7, 6, 8, 15 },
196 { 9, 9, 9, 9 },
197 { 6, 6, 9, 9 },
198 { 7, 17, 14, 9 },
199 { 7, 6, 14, 9 },
200 { 8, 9, 8, 9 },
201 { 16, 6, 8, 9 },
202 { 7, 17, 8, 9 },
203 { 7, 6, 8, 9 },
204 { 10, 10, 10, 10 },
205 { 7, 10, 14, 10 },
206 { 16, 10, 8, 10 },
207 { 7, 10, 8, 10 },
208 { 11, 11, 11, 11 },
209 { 11, 11, 8, 15 },
210 { 11, 11, 14, 9 },
211 { 11, 11, 8, 9 },
212 { 14, 14, 14, 14 },
213 { 14, 14, 8, 14 },
214 { 12, 12, 12, 12 },
215 { 12, 6, 12, 15 },
216 { 12, 17, 12, 9 },
217 { 12, 6, 12, 9 },
218 { 12, 10, 12, 10 },
219 { 15, 15, 15, 15 },
220 { 15, 15, 15, 9 },
221 { 15, 14, 12, 10 },
222 { 13, 13, 13, 13 },
223 { 16, 6, 13, 13 },
224 { 7, 17, 13, 13 },
225 { 7, 6, 13, 13 },
226 { 16, 16, 16, 16 },
227 { 7, 16, 16, 16 },
228 { 11, 11, 13, 13 },
229 { 11, 14, 13, 16 },
230 { 17, 17, 17, 17 },
231 { 17, 6, 17, 17 },
232 { 12, 10, 17, 16 },
233 { 15, 11, 17, 13 },
234 { 15, 14, 17, 16 },
235 { 18, 18, 18, 18 }
236 };
237
238 struct tile_move_data
239 {
240 int32_t copies;
241 int32_t dest_first;
242 int32_t dest_last;
243 int32_t src_first;
244 int32_t src_last;
245 int32_t dest_top;
246 int32_t dest_bottom;
247 int32_t src_top;
248 int32_t src_bottom;
249 int32_t src_left, src_right;
250 int32_t src_width, src_height;
251 int32_t dest_left, dest_right;
252 int32_t dest_width, dest_height;
253 int32_t rows, cols;
254 bool rect, move;
255
256 tile_move_data()
257 {
258 copies = dest_first = dest_last = src_first = src_last = dest_top =
259 dest_bottom = src_top = src_bottom = src_left = src_right =
260 src_width = src_height = dest_left = dest_right = dest_width =
261 dest_height = rows = cols = 0;
262 rect = move = false;
263 }
264
265 tile_move_data(tile_move_data const& other)
266 {
267 copy(other);
268 }
269
270 tile_move_data& operator=(tile_move_data const& other)
271 {
272 copy(other);
273 return *this;
274 }
275
276 void copy(tile_move_data const& other)
277 {
278 copies = other.copies;
279 dest_first = other.dest_first;
280 dest_last = other.dest_last;
281 src_first = other.src_first;
282 src_last = other.src_last;
283 dest_top = other.dest_top;
284 dest_bottom = other.dest_bottom;
285 src_top = other.src_top;
286 src_bottom = other.src_bottom;
287 src_left = other.src_left;
288 src_right = other.src_right;
289 src_width = other.src_width;
290 src_height = other.src_height;
291 dest_left = other.dest_left;
292 dest_right = other.dest_right;
293 dest_width = other.dest_width;
294 dest_height = other.dest_height;
295 rows = other.rows;
296 cols = other.cols;
297 rect = other.rect;
298 move = other.move;
299 }
300
301 void flip()
302 {
303 zc_swap(src_first, dest_first);
304 zc_swap(src_last, dest_last);
305 zc_swap(src_top, dest_top);
306 zc_swap(src_bottom, dest_bottom);
307 zc_swap(src_left, dest_left);
308 zc_swap(src_right, dest_right);
309 zc_swap(src_width, dest_width);
310 zc_swap(src_height, dest_height);
311 }
312 };
313 bool do_movetile_united(tile_move_data const& tmd);
314
315 struct combo_move_data
316 {
317 int32_t tile, tile2, copy1, copycnt;
318 combo_move_data() : tile(0), tile2(0), copy1(0), copycnt(0){}
319 combo_move_data(combo_move_data const& other)
320 {
321 copy(other);
322 }
323 combo_move_data& operator=(combo_move_data const& other)
324 {
325 copy(other);
326 return *this;
327 }
328 void copy(combo_move_data const& other)
329 {
330 tile = other.tile;
331 tile2 = other.tile2;
332 copy1 = other.copy1;
333 copycnt = other.copycnt;
334 }
335
336 void flip()
337 {
338 int32_t tcnt = tile2-tile+1;
339 int32_t cpy2 = copy1+copycnt-1;
340 zc_swap(tile,copy1);
341 tile2 = cpy2;
342 copycnt = tcnt;
343 }
344 };
345
346 bool do_movecombo(combo_move_data const& cmd, ComboMoveUndo& on_undo, bool is_undoing = false);
347 static optional<ComboMoveUndo> last_combo_move_list;
348 static optional<TileMoveUndo> last_tile_move_list;
349
350 int refl_flags = 0;
351 enum
352 {
353 REFL_90CW, REFL_HFLIP,
354 REFL_90CCW, REFL_VFLIP,
355 REFL_180, REFL_DBLFLIP,
356 REFL_MAX
357 };
358 const char *reflbtn_names[] =
359 {
360 "90 CW", "HFlip",
361 "90 CCW", "VFlip",
362 "180 Rot", "Diag Flip"
363 };
364 int bgmode = 0, xmode = 0;
365 const char *bgmodebtn_names[] =
366 {
367 "BG Color 0", "BG Trans."
368 };
369 const char *xmodebtn_names[] =
370 {
371 "X", "No X"
372 };
373 enum
374 {
375 XMODE_X, XMODE_NOX,
376 XMODE_MAX
377 };
378 enum
379 {
380 BGMODE_0, BGMODE_TRANSP,
381 BGMODE_MAX
382 };
383
384 void merge_tiles(int32_t dest_tile, int32_t src_quarter1, int32_t src_quarter2, int32_t src_quarter3, int32_t src_quarter4)
385 {
386 int32_t size=tilesize(newtilebuf[dest_tile].format)>>4;
387 int32_t size2=size>>1;
388
389 if(newtilebuf[dest_tile].data==NULL)
390 {
391 reset_tile(newtilebuf, dest_tile, newtilebuf[src_quarter1>>2].format);
392 }
393
394 int32_t i=0;
395
396 if((dest_tile<<2)+i!=src_quarter1)
397 {
398 for(int32_t j=0; j<8; ++j)
399 {
400 memcpy(&(newtilebuf[dest_tile].data[((j+((i&2)<<2))*size)+((i&1)*size2)]), &(newtilebuf[src_quarter1>>2].data[((j+((src_quarter1&2)<<2))*size)+((src_quarter1&1)*size2)]), size2);
401 }
402 }
403
404 i=1;
405
406 if((dest_tile<<2)+i!=src_quarter2)
407 {
408 for(int32_t j=0; j<8; ++j)
409 {
410 memcpy(&(newtilebuf[dest_tile].data[((j+((i&2)<<2))*size)+((i&1)*size2)]), &(newtilebuf[src_quarter2>>2].data[((j+((src_quarter2&2)<<2))*size)+((src_quarter2&1)*size2)]), size2);
411 }
412 }
413
414 i=2;
415
416 if((dest_tile<<2)+i!=src_quarter3)
417 {
418 for(int32_t j=0; j<8; ++j)
419 {
420 memcpy(&(newtilebuf[dest_tile].data[((j+((i&2)<<2))*size)+((i&1)*size2)]), &(newtilebuf[src_quarter3>>2].data[((j+((src_quarter3&2)<<2))*size)+((src_quarter3&1)*size2)]), size2);
421 }
422 }
423
424 i=3;
425
426 if((dest_tile<<2)+i!=src_quarter4)
427 {
428 for(int32_t j=0; j<8; ++j)
429 {
430 memcpy(&(newtilebuf[dest_tile].data[((j+((i&2)<<2))*size)+((i&1)*size2)]), &(newtilebuf[src_quarter4>>2].data[((j+((src_quarter4&2)<<2))*size)+((src_quarter4&1)*size2)]), size2);
431 }
432 }
433 }
434
435 static void make_combos(int32_t startTile, int32_t endTile, int32_t cs)
436 {
437 al_trace("inside make_combos()\n");
438 int32_t startCombo=0;
439
440 if(!select_combo_2(startCombo,cs))
441 return;
442
443 int32_t temp=combobuf[startCombo].o_tile;
444 combobuf[startCombo].set_tile(startTile);
445
446 if(!edit_combo(startCombo, false, cs))
447 {
448 combobuf[startCombo].set_tile(temp);
449 return;
450 }
451
452 go_combos();
453
454 for(int32_t i=0; i<=endTile-startTile; i++)
455 {
456 combobuf[startCombo+i]=combobuf[startCombo];
457 combobuf[startCombo+i].set_tile(startTile+i);
458 }
459
460 setup_combo_animations();
461 setup_combo_animations2();
462 }
463
464 static void make_combos_rect(int32_t top, int32_t left, int32_t numRows, int32_t numCols, int32_t cs)
465 {
466 int32_t startCombo=0;
467
468 if(!select_combo_2(startCombo, cs))
469 return;
470
471 int32_t startTile=top*TILES_PER_ROW+left;
472 int32_t temp=combobuf[startCombo].o_tile;
473 combobuf[startCombo].set_tile(startTile);
474
475 if(!edit_combo(startCombo, false, cs))
476 {
477 al_trace("make_combos_rect() early return\n");
478 combobuf[startCombo].set_tile(temp);
479 return;
480 }
481
482 bool smartWrap=false;
483 if(numCols!=4 && numRows>1)
484 {
485 char buf[64];
486 if(numCols<4)
487 sprintf(buf, "Limit to %d column%s?", numCols, numCols==1 ? "" : "s");
488 else
489 sprintf(buf, "Fit to 4 columns?"); // Meh, whatever.
490 int32_t ret=jwin_alert("Wrapping", buf, NULL, NULL, "&Yes", "&No", 'y', 'n', get_zc_font(font_lfont));
491 if(ret==1)
492 smartWrap=true;
493 }
494
495 go_combos();
496
497 int32_t combo=startCombo-1;
498 for(int32_t row=0; row<numRows; row++)
499 {
500 for(int32_t col=0; col<numCols; col++)
501 {
502 int32_t tile=startTile+row*TILES_PER_ROW+col;
503 if(smartWrap)
504 // Add 4 per row, and another numRows*4 for every 4 columns
505 // (col&0xFC==col/4*4), and then the column %4
506 combo=startCombo+4*row+(col&0xFC)*numRows+col%4;
507 else
508 combo++;
509
510 combobuf[combo]=combobuf[startCombo];
511 combobuf[combo].set_tile(tile);
512 }
513 }
514
515 setup_combo_animations();
516 setup_combo_animations2();
517 }
518
519 int32_t d_combo_proc(int32_t msg,DIALOG *d,int32_t c);
520
521 static bool nogotiles = false;
522 static bool nogocombos = false;
523
524 void go_tiles()
525 {
526 if(nogotiles) return;
527 last_tile_move_list = nullopt;
528 for(int32_t i=0; i<NEWMAXTILES; ++i)
529 {
530 newundotilebuf[i].format=newtilebuf[i].format;
531
532 if(newundotilebuf[i].data!=NULL)
533 {
534 free(newundotilebuf[i].data);
535 }
536
537 newundotilebuf[i].data=(byte *)malloc(tilesize(newundotilebuf[i].format));
538
539 if(newundotilebuf[i].data==NULL)
540 {
541 Z_error_fatal("Unable to initialize undo tile #%ld.\n", i);
542 }
543
544 memcpy(newundotilebuf[i].data,newtilebuf[i].data,tilesize(newundotilebuf[i].format));
545 }
546 }
547
548 void go_slide_tiles(int32_t columns, int32_t rows, int32_t top, int32_t left)
549 {
550 for(int32_t c=0; c<columns; c++)
551 {
552 for(int32_t r=0; r<rows; r++)
553 {
554 int32_t t=((top+r)*TILES_PER_ROW)+left+c;
555 newundotilebuf[t].format=newtilebuf[t].format;
556
557 if(newundotilebuf[t].data!=NULL)
558 {
559 free(newundotilebuf[t].data);
560 }
561
562 newundotilebuf[t].data=(byte *)malloc(tilesize(newundotilebuf[t].format));
563
564 if(newundotilebuf[t].data==NULL)
565 {
566 Z_error_fatal("Unable to initialize undo tile #%ld.\n", t);
567 }
568
569 memcpy(newundotilebuf[t].data,newtilebuf[t].data,tilesize(newundotilebuf[t].format));
570 }
571 }
572 }
573
574 void comeback_tiles()
575 {
576 if(last_tile_move_list)
577 {
578 last_tile_move_list->undo();
579 last_tile_move_list = nullopt;
580 }
581 for(dword i=0; i<NEWMAXTILES; ++i)
582 {
583 if(newtilebuf[i].format != newundotilebuf[i].format || !newtilebuf[i].data)
584 {
585 newtilebuf[i].format = newundotilebuf[i].format;
586
587 if(newtilebuf[i].data!=NULL)
588 free(newtilebuf[i].data);
589 newtilebuf[i].data=(byte *)malloc(tilesize(newtilebuf[i].format));
590 if(newtilebuf[i].data==NULL)
591 Z_error_fatal("Unable to initialize tile #%ld.\n", i);
592 }
593
594 memcpy(newtilebuf[i].data,newundotilebuf[i].data,tilesize(newtilebuf[i].format));
595 }
596
597 register_blank_tiles();
598 register_used_tiles();
599 }
600
601 void go_combos()
602 {
603 if(nogocombos) return;
604 last_combo_move_list = nullopt;
605
606 undocombobuf = combobuf;
607 }
608
609 void comeback_combos()
610 {
611 if(last_combo_move_list)
612 {
613 last_combo_move_list->undo();
614 last_combo_move_list = nullopt;
615 }
616
617 combobuf = undocombobuf;
618 }
619
620 void little_x(BITMAP *dest, int32_t x, int32_t y, int32_t c, int32_t s)
621 {
622 line(dest,x,y,x+s,y+s,c);
623 line(dest,x+s,y,x,y+s,c);
624 }
625 void little_x(BITMAP *dest, int32_t x, int32_t y, int32_t c, int32_t w, int32_t h)
626 {
627 line(dest,x,y,x+w,y+h,c);
628 line(dest,x+w,y,x,y+h,c);
629 }
630
631 enum {gm_light, gm_dark, gm_max};
632 int32_t gridmode=gm_light;
633
634 bool has_selection()
635 {
636 for(int32_t i=1; i<17; ++i)
637 {
638 for(int32_t j=1; j<17; ++j)
639 {
640 if(selection_grid[i][j])
641 {
642 return true;
643 }
644 }
645 }
646
647 return false;
648 }
649
650 void draw_selection_outline(BITMAP *dest, int32_t x, int32_t y, int32_t scale2)
651 {
652 drawing_mode(DRAW_MODE_COPY_PATTERN, selection_pattern, selection_anchor>>3, 0);
653
654 for(int32_t i=1; i<18; ++i)
655 {
656 for(int32_t j=1; j<18; ++j)
657 {
658 // zoomtile16(screen2,tile,79,31,cs,flip,8);
659 if(selection_grid[i-1][j]!=selection_grid[i][j])
660 {
661 vline(dest, x+((i-1)*scale2), y+((j-1)*scale2), y+(j*scale2), 255);
662 }
663
664 if(selection_grid[i][j-1]!=selection_grid[i][j])
665 {
666 hline(dest, x+((i-1)*scale2), y+((j-1)*scale2), x+(i*scale2), 255);
667 }
668 }
669 }
670
671 drawing_mode(DRAW_MODE_SOLID, NULL, 0, 0);
672 // selection_anchor=(selection_anchor+1)%64;
673 }
674
675 bool is_selecting()
676 {
677 return (selecting_x1>-1&&selecting_x2>-1&&selecting_y1>-1&&selecting_y2>-1);
678 }
679
680 void draw_selecting_outline(BITMAP *dest, int32_t x, int32_t y, int32_t scale2)
681 {
682 int32_t x1=zc_min(selecting_x1,selecting_x2);
683 int32_t x2=zc_max(selecting_x1,selecting_x2);
684 int32_t y1=zc_min(selecting_y1,selecting_y2);
685 int32_t y2=zc_max(selecting_y1,selecting_y2);
686
687 // rect(dest, x+(x1*scale2), y+(y1*scale2), x+((x2+1)*scale2), y+((y2+1)*scale2), 255);
688 for(int32_t i=1; i<18; ++i)
689 {
690 for(int32_t j=1; j<18; ++j)
691 {
692 drawing_mode(DRAW_MODE_COPY_PATTERN, selecting_pattern, selection_anchor>>3, 0);
693
694 if(((j>=y1+1)&&(j<=y2+1))&&((i==x1+1)||(i==x2+2)))
695 {
696 if(selection_grid[i-1][j]!=selection_grid[i][j])
697 {
698 drawing_mode(DRAW_MODE_COPY_PATTERN, intersection_pattern, selection_anchor>>3, 0);
699 }
700
701 vline(dest, x+((i-1)*scale2), y+((j-1)*scale2), y+(j*scale2), 255);
702 }
703
704 if(((i>=x1+1)&&(i<=x2+1))&&((j==y1+1)||(j==y2+2)))
705 {
706 if(selection_grid[i][j-1]!=selection_grid[i][j])
707 {
708 drawing_mode(DRAW_MODE_COPY_PATTERN, intersection_pattern, selection_anchor>>3, 0);
709 }
710
711 hline(dest, x+((i-1)*scale2), y+((j-1)*scale2), x+(i*scale2), 255);
712 }
713 }
714 }
715
716 drawing_mode(DRAW_MODE_SOLID, NULL, 0, 0);
717 // selection_anchor=(selection_anchor+1)%64;
718 }
719
720 void unfloat_selection();
721 bool floating_sel = false;
722 byte floatsel[256];
723 byte undofloatsel[256];
724 bool undo_is_floatsel = false;
725
726
727 void add_color_to_selection(int32_t color)
728 {
729 unfloat_selection();
730 for(int32_t i=1; i<17; ++i)
731 {
732 for(int32_t j=1; j<17; ++j)
733 {
734 if(unpackbuf[((j-1)<<4)+(i-1)]==color)
735 {
736 selection_grid[i][j]=1;
737 }
738 }
739 }
740 }
741
742 void remove_color_from_selection(int32_t color)
743 {
744 unfloat_selection();
745 for(int32_t i=1; i<17; ++i)
746 {
747 for(int32_t j=1; j<17; ++j)
748 {
749 if(unpackbuf[((j-1)<<4)+(i-1)]==color)
750 {
751 selection_grid[i][j]=0;
752 }
753 }
754 }
755 }
756
757 void intersect_color_with_selection(int32_t color)
758 {
759 unfloat_selection();
760 for(int32_t i=1; i<17; ++i)
761 {
762 for(int32_t j=1; j<17; ++j)
763 {
764 if((unpackbuf[((j-1)<<4)+(i-1)]==color)&&(selection_grid[i][j]==1))
765 {
766 selection_grid[i][j]=1;
767 }
768 else
769 {
770 selection_grid[i][j]=0;
771 }
772 }
773 }
774 }
775
776 bool is_in_selection(int32_t x, int32_t y)
777 {
778 x %= 16; y %= 16;
779 if(x < 0) x = (16 - abs(x));
780 if(y < 0) y = (16 - abs(y));
781 return (!has_selection()||(selection_grid[x+1][y+1]!=0));
782 }
783
784 void zoomtile16(BITMAP *dest,int32_t tile,int32_t x,int32_t y,int32_t cset,int32_t flip,int32_t m)
785 {
786 // rectfill(dest,x,y,x+(16*m),y+(16*m),gridmode==gm_light?jwin_pal[jcMEDLT]:jwin_pal[jcDARK]);
787 int gridcol = gridmode==gm_light?vc(7):vc(8);
788
789 cset <<= 4;
790 if(newtilebuf[tile].format>tf4Bit)
791 cset=0;
792
793 int g = hide_grid ? 1 : 0;
794 byte transp_col = (bgmode == BGMODE_TRANSP ? jwin_pal[jcBOX] : 0+cset);
795 rectfill(dest,x,y,x+(16*m)+g,y+(16*m)+g,transp_col);
796
797 unpack_tile(newtilebuf, tile, 0, false);
798 byte *si = unpackbuf;
799 for(int32_t cy=0; cy<16; cy++)
800 {
801 for(int32_t cx=0; cx<16; cx++)
802 {
803 byte col = (floating_sel && floatsel[cx+(cy<<4)]) ? floatsel[cx+(cy<<4)] : *si;
804 int32_t dx = ((flip&1)?15-cx:cx)*m;
805 int32_t dy = ((flip&2)?15-cy:cy)*m;
806 if(col)
807 rectfill(dest,x+dx,y+dy,x+dx+m-1,y+dy+m-1,col+cset);
808
809 if(!col && xmode == XMODE_X)
810 little_x(dest,x+dx+m/4,y+dy+m/4,invcol,m/2);
811
812 ++si;
813 }
814 }
815
816 if(!hide_grid)
817 {
818 for(int cx = 0; cx <= 16; ++cx)
819 vline(dest,x+(cx*m),y,y+(16*m)-1,gridcol);
820 for(int cy = 0; cy <= 16; ++cy)
821 hline(dest,x,y+(cy*m),x+(16*m)-1,gridcol);
822 }
823
824 if(show_quartgrid)
825 {
826 int offs = (8*m);
827 const int RAD = 3;
828 rectfill(dest,x+offs-RAD,y,x+offs+RAD,y+(16*m),gridcol);
829 rectfill(dest,x,y+offs-RAD,x+(16*m),y+offs+RAD,gridcol);
830 }
831
832 if(has_selection()||is_selecting())
833 {
834 selection_anchor=(selection_anchor+1)%64;
835
836 if(has_selection()||is_selecting())
837 draw_selection_outline(dest, x, y, m);
838
839 if(is_selecting())
840 draw_selecting_outline(dest, x, y, m);
841 }
842 }
843
844 void draw_text_button(BITMAP *dest,int32_t x,int32_t y,int32_t w,int32_t h,const char *text,int32_t bg,int32_t fg,int32_t flags,bool jwin)
845 {
846 if(!jwin)
847 {
848 if(flags&D_SELECTED)
849 {
850 zc_swap(fg,bg);
851 }
852
853 rect(dest,x+1,y+1,x+w-1,y+h-1,fg);
854 rectfill(dest,x+1,y+1,x+w-3,y+h-3,bg);
855 rect(dest,x,y,x+w-2,y+h-2,fg);
856 textout_centre_ex(dest,font,text,(x+x+w)>>1,((y+y+h)>>1)-4,fg,-1);
857 }
858 else
859 {
860 jwin_draw_text_button(dest, x, y, w, h, text, flags, true);
861 }
862 }
863
864 void draw_icon_button(BITMAP *dest,int32_t x,int32_t y,int32_t w,int32_t h,int icon,int32_t bg,int32_t fg,int32_t flags,bool jwin)
865 {
866 if(!jwin)
867 {
868 if(flags&D_SELECTED)
869 {
870 zc_swap(fg,bg);
871 }
872
873 rect(dest,x+1,y+1,x+w-1,y+h-1,fg);
874 rectfill(dest,x+1,y+1,x+w-3,y+h-3,bg);
875 rect(dest,x,y,x+w-2,y+h-2,fg);
876 jwin_draw_icon(dest,x+w/2,y+h/2,fg,icon,icon_proportion(icon,w,h),true);
877 }
878 else
879 {
880 jwin_draw_icon_button(dest, x, y, w, h, icon, flags, true);
881 }
882 }
883
884 void draw_layer_button(BITMAP *dest,int32_t x,int32_t y,int32_t w,int32_t h,const char *text,int32_t flags)
885 {
886 if(flags&D_SELECTED)
887 {
888 rect(dest, x, y, x+w-1, y+h-1, jwin_pal[jcDARK]);
889 ++x;
890 ++y;
891 --w;
892 --h;
893 }
894 rectfill(dest,x+1,y+1,x+w-3,y+h-3,jwin_pal[(flags&D_SELECTED ? jcMEDDARK : jcBOX)]);
895 jwin_draw_frame(dest, x, y, w, h, (flags&D_SELECTED ? FR_DARK : FR_BOX));
896
897 //Forcibly fit the text within the button
898 char buf[512] = {0};
899 strcpy(buf, text);
900
901 bool dis = (flags&D_DISABLED);
902 auto hei = text_height(font);
903 auto len = text_length(font,buf);
904 auto borderwid = 8;
905 if(len > w - borderwid + (dis ? 1 : 0))
906 {
907 auto ind = strlen(buf) - 1;
908 auto dotcount = 0;
909 while(len > w - borderwid + (dis ? 1 : 0))
910 {
911 if(dotcount >= 2)
912 buf[ind+2] = 0;
913 else ++dotcount;
914 buf[ind--] = '.';
915 len = text_length(font,buf);
916 }
917 }
918 if(dis)
919 {
920 ++len; ++hei;
921 }
922 BITMAP* tmp = create_bitmap_ex(8,len,hei);
923 clear_bitmap(tmp);
924 if(dis)
925 {
926 textout_ex(tmp,font,buf,1,1,jwin_pal[jcLIGHT],-1);
927 textout_ex(tmp,font,buf,0,0,jwin_pal[jcDISABLED_FG],-1);
928 }
929 else
930 textout_ex(tmp,font,buf,0,0,jwin_pal[jcBOXFG],-1);
931 auto tx = x+((w-len)/2);
932 auto ty = y+((h-hei)/2);
933 if(len > w-borderwid)
934 {
935 tx = x+borderwid/2;
936 len = w-borderwid;
937 }
938 if(hei > h-borderwid)
939 {
940 ty = y+borderwid/2;
941 hei = h-borderwid;
942 }
943 masked_blit(tmp,dest, 0,0, tx,ty, len, hei);
944 destroy_bitmap(tmp);
945 }
946
947 bool do_layer_button_reset(int32_t x,int32_t y,int32_t w,int32_t h,const char *text, int32_t flags, bool toggleflag)
948 {
949 bool over=false;
950
951 while(gui_mouse_b())
952 {
953 //vsync();
954 if(mouse_in_rect(x,y,w,h))
955 {
956 if(!over)
957 {
958 vsync();
959 draw_layer_button(screen, x, y, w, h, text, flags^D_SELECTED);
960 over=true;
961
962 update_hw_screen();
963 }
964 }
965 else
966 {
967 if(over)
968 {
969 vsync();
970 draw_layer_button(screen, x, y, w, h, text, flags);
971 over=false;
972
973 update_hw_screen();
974 }
975 }
976 rest(1);
977 }
978
979 if(over)
980 {
981 vsync();
982 draw_layer_button(screen, x, y, w, h, text, toggleflag ? flags^D_SELECTED : flags);
983
984 update_hw_screen();
985 }
986
987 return over;
988 }
989
990 bool do_text_button_reset(int32_t x,int32_t y,int32_t w,int32_t h,const char *text,int32_t bg,int32_t fg,bool jwin, bool sel)
991 {
992 bool over=false;
993
994 while(gui_mouse_b())
995 {
996 custom_vsync();
997
998 if(isinRect(gui_mouse_x(),gui_mouse_y(),x,y,x+w-1,y+h-1))
999 {
1000 if(!over)
1001 {
1002 draw_text_button(screen,x,y,w,h,text,fg,bg,sel?0:D_SELECTED,jwin);
1003 over=true;
1004 }
1005 }
1006 else
1007 {
1008 if(over)
1009 {
1010 draw_text_button(screen,x,y,w,h,text,fg,bg,sel?D_SELECTED:0,jwin);
1011 over=false;
1012 }
1013 }
1014 }
1015
1016 if(over)
1017 {
1018 custom_vsync();
1019 draw_text_button(screen,x,y,w,h,text,fg,bg,sel?0:D_SELECTED,jwin);
1020 }
1021
1022 return over;
1023 }
1024
1025 void draw_graphics_button(BITMAP *dest,int32_t x,int32_t y,int32_t w,int32_t h,BITMAP *bmp,BITMAP *bmp2,int32_t bg,int32_t fg,int32_t flags,bool jwin,bool overlay)
1026 {
1027 if(!jwin)
1028 {
1029 if(flags&D_SELECTED)
1030 {
1031 zc_swap(fg,bg);
1032 }
1033
1034 rect(dest,x+1,y+1,x+w-1,y+h-1,fg);
1035 rectfill(dest,x+1,y+1,x+w-3,y+h-3,bg);
1036 rect(dest,x,y,x+w-2,y+h-2,fg);
1037 int32_t g = (flags & D_SELECTED) ? 1 : 0;
1038
1039 if(overlay)
1040 {
1041 masked_blit(bmp, dest, 0, 0, x+w/2+g, y+h/2-bmp->h/2+g, bmp->h, bmp->w);
1042 }
1043 else
1044 {
1045 blit(bmp, dest, 0, 0, x+w/2+g, y+h/2-bmp->h/2+g, bmp->h, bmp->w);
1046 }
1047 }
1048 else
1049 {
1050 jwin_draw_graphics_button(dest, x, y, w, h, bmp, bmp2, flags, false, overlay);
1051 }
1052 }
1053
1054 bool do_graphics_button(int32_t x,int32_t y,int32_t w,int32_t h,BITMAP *bmp,BITMAP *bmp2,int32_t bg,int32_t fg,bool jwin,bool overlay)
1055 {
1056 bool over=false;
1057
1058 while(gui_mouse_b())
1059 {
1060 custom_vsync();
1061
1062 if(isinRect(gui_mouse_x(),gui_mouse_y(),x,y,x+w-1,y+h-1))
1063 {
1064 if(!over)
1065 {
1066 draw_graphics_button(screen,x,y,w,h,bmp,bmp2,fg,bg,D_SELECTED,jwin,overlay);
1067 over=true;
1068 }
1069 }
1070 else
1071 {
1072 if(over)
1073 {
1074 draw_graphics_button(screen,x,y,w,h,bmp,bmp2,fg,bg,0,jwin,overlay);
1075 over=false;
1076 }
1077 }
1078 }
1079
1080 return over;
1081 }
1082
1083 bool do_graphics_button_reset(int32_t x,int32_t y,int32_t w,int32_t h,BITMAP *bmp,BITMAP *bmp2,int32_t bg,int32_t fg,bool jwin,bool overlay)
1084 {
1085 bool over=false;
1086
1087 while(gui_mouse_b())
1088 {
1089 custom_vsync();
1090
1091 if(isinRect(gui_mouse_x(),gui_mouse_y(),x,y,x+w-1,y+h-1))
1092 {
1093 if(!over)
1094 {
1095 draw_graphics_button(screen,x,y,w,h,bmp,bmp2,fg,bg,D_SELECTED,jwin,overlay);
1096 over=true;
1097 }
1098 }
1099 else
1100 {
1101 if(over)
1102 {
1103 draw_graphics_button(screen,x,y,w,h,bmp,bmp2,fg,bg,0,jwin,overlay);
1104 over=false;
1105 }
1106 }
1107 }
1108
1109 if(over)
1110 {
1111 custom_vsync();
1112 draw_graphics_button(screen,x,y,w,h,bmp,bmp2,fg,bg,0,jwin,overlay);
1113 }
1114
1115 return over;
1116 }
1117 // circle(BITMAP *bmp, int32_t x, int32_t y, int32_t radius, int32_t color);
1118 // circlefill(BITMAP *bmp, int32_t x, int32_t y, int32_t radius, int32_t color);
1119
1120 void draw_layerradio(BITMAP *dest,int32_t x,int32_t y,int32_t bg,int32_t fg, int32_t value)
1121 {
1122 //these are here to bypass compiler warnings about unused arguments
1123 bg=bg;
1124 fg=fg;
1125
1126 int32_t r, center;
1127
1128 for(int32_t k=0; k<7; k++)
1129 {
1130 if((k==0)||(Map.CurrScr()->layermap[k-1]))
1131 {
1132 // circle(dest, x+(k*25)+4, y+4, 4, fg);
1133 // circlefill(dest, x+(k*25)+4, y+4, 2, (value==k)?fg:bg);
1134 //*
1135 r = 9/2;
1136
1137 center = x+(k*25)+r;
1138 rectfill(dest, x+(k*25), y, x+(k*25)+9-1, y+9-1, jwin_pal[jcBOX]);
1139
1140 circlefill(dest, center, y+r, r, jwin_pal[jcLIGHT]);
1141 arc(dest, center, y+r, itofix(32), itofix(160), r, jwin_pal[jcMEDDARK]);
1142 circlefill(dest, center, y+r, r-1, jwin_pal[jcMEDLT]);
1143 arc(dest, center, y+r, itofix(32), itofix(160), r-1, jwin_pal[jcDARK]);
1144 circlefill(dest, center, y+r, r-2, jwin_pal[jcLIGHT]);
1145
1146 if(value==k)
1147 {
1148 circlefill(dest, center, y+r, r-3, jwin_pal[jcDARK]);
1149 }
1150
1151 //*/
1152 }
1153 }
1154 }
1155
1156 void do_layerradio(BITMAP *dest,int32_t x,int32_t y,int32_t bg,int32_t fg,int32_t &value)
1157 {
1158 while(gui_mouse_b())
1159 {
1160 custom_vsync();
1161
1162 for(int32_t k=0; k<7; k++)
1163 {
1164 if((k==0)||(Map.CurrScr()->layermap[k-1]))
1165 {
1166 //if on radio button
1167 if(isinRect(gui_mouse_x(),gui_mouse_y(),x+(k*25),y,x+(k*25)+8,y+8))
1168 {
1169 value=k;
1170 draw_layerradio(dest,x,y,bg,fg,value);
1171 refresh(rMENU);
1172 }
1173 }
1174 }
1175 }
1176 }
1177
1178 //*************** tile flood fill stuff **************
1179
1180 byte tf_c;
1181 byte tf_u;
1182
1183 void tile_floodfill_rec(int32_t x,int32_t y)
1184 {
1185 if(is_in_selection(x,y))
1186 {
1187 while(x>0 && (unpackbuf[(y<<4)+x-1] == tf_u))
1188 --x;
1189
1190 while(x<=15 && (unpackbuf[(y<<4)+x] == tf_u))
1191 {
1192 if(is_in_selection(x,y))
1193 {
1194 unpackbuf[(y<<4)+x] = tf_c;
1195 }
1196
1197 if(y>0 && (unpackbuf[((y-1)<<4)+x] == tf_u))
1198 tile_floodfill_rec(x,y-1);
1199
1200 if(y<15 && (unpackbuf[((y+1)<<4)+x] == tf_u))
1201 tile_floodfill_rec(x,y+1);
1202
1203 ++x;
1204 }
1205 }
1206 }
1207
1208 void tile_floodfill(int32_t tile,int32_t x,int32_t y,byte c)
1209 {
1210 if(is_in_selection(x,y))
1211 {
1212 if(floating_sel)
1213 {
1214 memcpy(unpackbuf, floatsel, 256);
1215 }
1216 else unpack_tile(newtilebuf, tile, 0, false);
1217 tf_c = c;
1218 tf_u = unpackbuf[(y<<4)+x];
1219
1220 if(tf_u != tf_c)
1221 tile_floodfill_rec(x,y);
1222 if(floating_sel)
1223 {
1224 memcpy(floatsel, unpackbuf, 256);
1225 }
1226 else pack_tile(newtilebuf,unpackbuf,tile);
1227 }
1228 }
1229
1230 //***************** tile editor stuff *****************
1231 9 size_and_pos ok_button(302,562,71,21);
1232 9 size_and_pos cancel_button(376,562,71,21);
1233 9 size_and_pos edit_button(550,562,86,21);
1234 9 size_and_pos hlcbox(742,392,16,16);
1235 9 size_and_pos hov_prev(742,338,50,50);
1236 9 size_and_pos cpalette_4(648,416,4,4,64,64);
1237 9 size_and_pos cpalette_8(648,416,16,14,16,18);
1238 9 size_and_pos fg_prev(648,316,50,50);
1239 9 size_and_pos bg_prev(648+30,316+30,50,50);
1240 9 size_and_pos zoomtile(124,32,16,16,32,32);
1241 9 size_and_pos prev_til_1(648,31,96,96);
1242 9 size_and_pos prev_til_2(752,31,96,96);
1243 9 size_and_pos prev_til_3(648,135,96,96);
1244 9 size_and_pos prev_til_4(752,135,96,96);
1245 9 size_and_pos status_info(648,308-(4*8),1,4,1,8);
1246 9 size_and_pos hover_info(742,338-(3*8),1,3,1,8);
1247 9 size_and_pos color_info(4,189,1,1,116,8);
1248 9 size_and_pos color_info_btn(24,189,96,21);
1249 9 size_and_pos tool_btns(22,29,2,4,39,39);
1250 9 size_and_pos x_btn(890,5,15,13);
1251 9 size_and_pos info_btn(872,5,15,13);
1252 9 size_and_pos hidegrid_cbox(124,552,16,16);
1253 9 size_and_pos quartgrid_cbox(124,572,16,16);
1254 9 size_and_pos reflbtn_grid(124,610,2,3,71,21);
1255 9 size_and_pos xmodebtn_grid(300,610,1,2,90,21);
1256 9 size_and_pos bgmodebtn_grid(390,610,1,2,90,21);
1257
1258 int32_t c1=1;
1259 int32_t c2=0;
1260 int32_t floating_tile = -1;
1261 int32_t tool = t_pen;
1262 int32_t old_tool = -1;
1263 int32_t tool_cur = -1;
1264 int32_t select_mode = 0;
1265 int32_t drawing=0;
1266
1267 bool qgrid_tool(int tool)
1268 {
1269 switch(tool)
1270 {
1271 case t_pen:
1272 case t_fill:
1273 case t_recolor:
1274 case t_wand:
1275 return true;
1276 }
1277 return false;
1278 }
1279
1280 void set_tool_sprite(int tool, int type)
1281 {
1282 int spr = ZQM_NORMAL;
1283 switch(tool)
1284 {
1285 case t_pen: spr = ZQM_SWORD; break;
1286 case t_fill: spr = ZQM_POTION; break;
1287 case t_recolor: spr = ZQM_WAND; break;
1288 case t_eyedropper: spr = ZQM_LENS; break;
1289 case t_move: spr = ZQM_GLOVE_OPEN+type; break;
1290 case t_select: spr = ZQM_HOOK_PLAIN+type; break;
1291 case t_wand: spr = ZQM_SEL_WAND_PLAIN+type; break;
1292 }
1293 MouseSprite::set(spr);
1294 }
1295 void update_tool_cursor()
1296 {
1297 int32_t temp_mouse_x=gui_mouse_x();
1298 int32_t temp_mouse_y=gui_mouse_y();
1299
1300 int32_t type=0;
1301
1302 if(has_selection())
1303 {
1304 switch(tool)
1305 {
1306 case t_select:
1307 case t_wand:
1308 type+=select_mode;
1309 break;
1310 }
1311 }
1312
1313 if(isinRect(temp_mouse_x,temp_mouse_y,zoomtile.x,zoomtile.y-(tool==t_fill ? (14) : 0),zoomtile.x+(zoomtile.w*zoomtile.xscale)-2,zoomtile.y+(zoomtile.h*zoomtile.yscale)-2-(tool==t_fill ? (14) : 0))) //inside the zoomed tile window
1314 {
1315 if(tool_cur==-1)
1316 set_tool_sprite(tool,type);
1317
1318 tool_cur=tool;
1319 }
1320 else if(tool_cur != -1)
1321 {
1322 MouseSprite::set(ZQM_NORMAL);
1323 tool_cur = -1;
1324 }
1325 }
1326
1327 void draw_edit_scr(int32_t tile,int32_t flip,int32_t cs,byte *oldtile, bool create_tbar)
1328 {
1329 PALETTE tpal;
1330 static BITMAP *tbar = create_bitmap_ex(8,zq_screen_w-6, 18);
1331 static BITMAP *preview_bmp = create_bitmap_ex(8, 64, 64);
1332 jwin_draw_win(screen2, 0, 0, zq_screen_w, zq_screen_h, FR_WIN);
1333
1334 if(!create_tbar)
1335 {
1336 blit(tbar, screen2, 0, 0, 3, 3, zq_screen_w-6, 18);
1337 }
1338 else
1339 {
1340 jwin_draw_titlebar(tbar, 0, 0, zq_screen_w-6, 18, "", true, true);
1341 blit(tbar, screen2, 0, 0, 3, 3, zq_screen_w-6, 18);
1342 }
1343
1344 textprintf_ex(screen2,get_zc_font(font_lfont),5,5,jwin_pal[jcTITLEFG],-1,"Tile Editor (%d)",tile);
1345
1346 clear_to_color(preview_bmp, 0);
1347
1348 zc_swap(oldtile,newtilebuf[tile].data); //Put oldtile in the tile buffer
1349 jwin_draw_win(screen2, prev_til_1.x-2,prev_til_1.y-2, prev_til_1.w+4, prev_til_1.h+4, FR_DEEP);
1350 puttile16(preview_bmp,tile,0,0,cs,flip);
1351 stretch_blit(preview_bmp, screen2, 0, 0, 16, 16, prev_til_1.x, prev_til_1.y, prev_til_1.w, prev_til_1.h);
1352
1353 clear_to_color(preview_bmp, 0);
1354 jwin_draw_win(screen2, prev_til_2.x-2,prev_til_2.y-2, prev_til_2.w+4, prev_til_2.h+4, FR_DEEP);
1355 overtile16(preview_bmp,tile,0,0,cs,flip);
1356 masked_stretch_blit(preview_bmp, screen2, 0, 0, 16, 16, prev_til_2.x, prev_til_2.y, prev_til_2.w, prev_til_2.h);
1357 zc_swap(oldtile,newtilebuf[tile].data); //Swap the real tile back to the buffer
1358
1359 unpack_tile(newtilebuf, tile, 0, true);
1360 if(floating_sel)
1361 for(auto q = 0; q < 256; ++q)
1362 if(floatsel[q])
1363 unpackbuf[q] = floatsel[q];
1364 byte tmptile[256];
1365 byte *tmpptr = tmptile;
1366 zc_swap(tmpptr,newtilebuf[tile].data); //Put temp data in the tile buffer
1367 pack_tile(newtilebuf,unpackbuf,tile);
1368 clear_to_color(preview_bmp, 0);
1369
1370 jwin_draw_win(screen2, prev_til_3.x-2,prev_til_3.y-2, prev_til_3.w+4, prev_til_3.h+4, FR_DEEP);
1371 puttile16(preview_bmp,tile,0,0,cs,flip);
1372 stretch_blit(preview_bmp, screen2, 0, 0, 16, 16, prev_til_3.x, prev_til_3.y, prev_til_3.w, prev_til_3.h);
1373
1374 clear_to_color(preview_bmp, 0);
1375 jwin_draw_win(screen2, prev_til_4.x-2,prev_til_4.y-2, prev_til_4.w+4, prev_til_4.h+4, FR_DEEP);
1376 overtile16(preview_bmp,tile,0,0,cs,flip);
1377 masked_stretch_blit(preview_bmp, screen2, 0, 0, 16, 16, prev_til_4.x, prev_til_4.y, prev_til_4.w, prev_til_4.h);
1378
1379 //Color info
1380 {
1381 auto fh = color_info.yscale = text_height(font);
1382 int y = color_info.y;
1383 int rx = color_info.x+color_info.xscale;
1384 color_info.h = 1;
1385 if(showcolortip)
1386 {
1387 gui_textout_ln(screen2,font,(unsigned char*)"Colors:",
1388 rx,y,jwin_pal[jcBOXFG],jwin_pal[jcBOX],2);
1389 auto str = get_tile_colornames(tile,cs);
1390 size_t pos = 0;
1391 char buf[512] = {0};
1392 char cbuf[16] = {0};
1393 while(pos < str.size())
1394 {
1395 y += fh;
1396 if(y+fh > zq_screen_h)
1397 break; //Out of space!
1398 auto endpos = str.find_first_of('\n',pos);
1399
1400 if(endpos == std::string::npos)
1401 {
1402 strcpy(buf,str.substr(pos).c_str());
1403 pos = str.size();
1404 }
1405 else
1406 {
1407 strcpy(buf,str.substr(pos,endpos-pos+1).c_str());
1408 pos = endpos+1;
1409 }
1410 //Ensure the name fits horizontally
1411 if(text_length(font,buf) > color_info.xscale)
1412 {
1413 size_t pos = 0;
1414 for(; buf[pos]; ++pos)
1415 {
1416 if(buf[pos] == ':')
1417 {
1418 strcpy(cbuf, buf+pos);
1419 buf[pos] = 0;
1420 break;
1421 }
1422 }
1423 size_t clen = text_length(font,cbuf);
1424 size_t dotlen = text_length(font,"..");
1425
1426 while(pos > 0 && (dotlen+clen+text_length(font,buf) > color_info.xscale))
1427 buf[--pos] = 0;
1428 while(buf[pos] == ' ')
1429 buf[pos] = 0;
1430 strcat(buf,"..");
1431 strcat(buf,cbuf);
1432 }
1433 gui_textout_ln(screen2,font,(unsigned char const*)buf,
1434 rx,y,jwin_pal[jcBOXFG],jwin_pal[jcBOX],2);
1435 ++color_info.h;
1436 }
1437 jwin_draw_frame(screen2,color_info.x-2,color_info.y-2,(color_info.w*color_info.xscale)+4,(color_info.h*color_info.yscale)+4,FR_DEEP);
1438 }
1439 else
1440 {
1441 draw_text_button(screen2,color_info_btn.x,color_info_btn.y,color_info_btn.w,color_info_btn.h,
1442 "Show Colors",vc(1),vc(14),0,true);
1443 }
1444 }
1445
1446 zc_swap(tmpptr,newtilebuf[tile].data); //Swap the real tile back to the buffer
1447
1448 jwin_draw_win(screen2, zoomtile.x-3, zoomtile.y-3, (zoomtile.w*zoomtile.xscale)+5, (zoomtile.h*zoomtile.yscale)+5, FR_DEEP);
1449 zoomtile16(screen2,tile,zoomtile.x-1,zoomtile.y-1,cs,flip,zoomtile.xscale);
1450
1451 if(floating_sel)
1452 textprintf_ex(screen2,font,status_info.x,status_info.y+0,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"Floating selection");
1453 textprintf_ex(screen2,font,status_info.x,status_info.y+(1*status_info.yscale),jwin_pal[jcBOXFG],jwin_pal[jcBOX],"tile: %d",tile);
1454 if(newtilebuf[tile].format==tf8Bit)
1455 textprintf_ex(screen2,font,status_info.x,status_info.y+(2*status_info.yscale),jwin_pal[jcBOXFG],jwin_pal[jcBOX],"8-bit");
1456 else
1457 textprintf_ex(screen2,font,status_info.x,status_info.y+(2*status_info.yscale),jwin_pal[jcBOXFG],jwin_pal[jcBOX],"cset: %d",cs);
1458
1459 PALETTE temppal;
1460
1461 //palette and mouse
1462 switch(newtilebuf[tile].format)
1463 {
1464 case tf4Bit:
1465 jwin_draw_win(screen2, cpalette_4.x-2, cpalette_4.y-2, (cpalette_4.xscale*cpalette_4.w)+4, (cpalette_4.yscale*cpalette_4.h)+4, FR_DEEP);
1466 get_palette(temppal);
1467
1468 for(int32_t i=0; i<cpalette_4.w*cpalette_4.h; i++)
1469 {
1470 size_and_pos const& s = cpalette_4.subsquare(i);
1471 rectfill(screen2,s.x,s.y,s.x+s.w-1,s.y+s.h-1,CSET(cs)+i);
1472 }
1473
1474 little_x(screen2,cpalette_4.x+1,cpalette_4.y+1,invcol,cpalette_4.xscale-5,cpalette_4.yscale-5);
1475 break;
1476
1477 case tf8Bit:
1478 jwin_draw_win(screen2, cpalette_8.x-2, cpalette_8.y-2, (cpalette_8.xscale*cpalette_8.w)+4, (cpalette_8.yscale*cpalette_8.h)+4, FR_DEEP);
1479
1480 for(int32_t i=0; i<cpalette_8.w*cpalette_8.h; ++i)
1481 {
1482 size_and_pos const& s = cpalette_8.subsquare(i);
1483 rectfill(screen2,s.x,s.y,s.x+s.w-1,s.y+s.h-1,i);
1484 }
1485
1486 little_x(screen2,cpalette_8.x+1,cpalette_8.y+1,invcol,cpalette_8.xscale-5,cpalette_8.yscale-5);
1487 break;
1488 }
1489
1490 rect(screen2, bg_prev.x, bg_prev.y, bg_prev.x+bg_prev.w-1, bg_prev.y+bg_prev.h-1, jwin_pal[jcTEXTFG]);
1491 rectfill(screen2, bg_prev.x+1, bg_prev.y+1, bg_prev.x+bg_prev.w-2, bg_prev.y+bg_prev.h-2, jwin_pal[jcTEXTBG]);
1492 rectfill(screen2, bg_prev.x+3, bg_prev.y+3, bg_prev.x+bg_prev.w-4, bg_prev.y+bg_prev.h-4, c2+((newtilebuf[tile].format==tf4Bit)?CSET(cs):0));
1493
1494 if(c2==0)
1495 {
1496 little_x(screen2, bg_prev.x+1, bg_prev.y+1, invcol, bg_prev.w-2, bg_prev.h-2);
1497 }
1498
1499 rect(screen2, fg_prev.x, fg_prev.y, fg_prev.x+fg_prev.w-1, fg_prev.y+fg_prev.h-1, jwin_pal[jcTEXTFG]);
1500 rectfill(screen2, fg_prev.x+1, fg_prev.y+1, fg_prev.x+fg_prev.w-2, fg_prev.y+fg_prev.h-2, jwin_pal[jcTEXTBG]);
1501 rectfill(screen2, fg_prev.x+3, fg_prev.y+3, fg_prev.x+fg_prev.w-4, fg_prev.y+fg_prev.h-4, c1+((newtilebuf[tile].format==tf4Bit)?CSET(cs):0));
1502
1503 if(c1==0)
1504 {
1505 little_x(screen2, fg_prev.x+1, fg_prev.y+1, invcol, fg_prev.w-2, fg_prev.h-2);
1506 }
1507
1508 draw_text_button(screen2,ok_button.x,ok_button.y,ok_button.w,ok_button.h,"OK",vc(1),vc(14),0,true);
1509 draw_text_button(screen2,cancel_button.x,cancel_button.y,cancel_button.w,cancel_button.h,"Cancel",vc(1),vc(14),0,true);
1510 draw_text_button(screen2,edit_button.x,edit_button.y,edit_button.w,edit_button.h,"Edit Pal",vc(1),vc(14),0,true);
1511 draw_checkbox(screen2,hlcbox.x, hlcbox.y, hlcbox.w, hlcbox.h, tthighlight);
1512 gui_textout_ln(screen2,font,(unsigned char*)"Highlight Hover",hlcbox.x+hlcbox.w+2,hlcbox.y+hlcbox.h/2-text_height(font)/2,jwin_pal[jcBOXFG],jwin_pal[jcBOX],0);
1513
1514 draw_checkbox(screen2,quartgrid_cbox.x, quartgrid_cbox.y, quartgrid_cbox.w, quartgrid_cbox.h, show_quartgrid);
1515 gui_textout_ln(screen2,font,(unsigned char*)"Quarter Grid",quartgrid_cbox.x+quartgrid_cbox.w+2,quartgrid_cbox.y+quartgrid_cbox.h/2-text_height(font)/2,jwin_pal[jcBOXFG],jwin_pal[jcBOX],0);
1516
1517 draw_checkbox(screen2,hidegrid_cbox.x, hidegrid_cbox.y, hidegrid_cbox.w, hidegrid_cbox.h, hide_grid);
1518 gui_textout_ln(screen2,font,(unsigned char*)"Hide Grid",hidegrid_cbox.x+hidegrid_cbox.w+2,hidegrid_cbox.y+hidegrid_cbox.h/2-text_height(font)/2,jwin_pal[jcBOXFG],jwin_pal[jcBOX],0);
1519
1520 bool qgrd = show_quartgrid && qgrid_tool(tool);
1521 gui_textout_ln(screen2,font,(unsigned char*)"Quarter-Grid Draw Modes", reflbtn_grid.x, reflbtn_grid.y-text_height(font)-4,jwin_pal[jcBOXFG],jwin_pal[jcBOX],qgrd?0:D_DISABLED);
1522 for(int q = 0; q < REFL_MAX; ++q)
1523 {
1524 auto& sqr = reflbtn_grid.subsquare(q);
1525 draw_text_button(screen2,sqr.x,sqr.y,sqr.w,sqr.h,reflbtn_names[q],vc(1),vc(14),qgrd ? ((refl_flags&(1<<q)) ? D_SELECTED : 0) : D_DISABLED,true);
1526 }
1527 gui_textout_ln(screen2,font,(unsigned char*)"Transparent Mode", xmodebtn_grid.x, xmodebtn_grid.y-text_height(font)-4,jwin_pal[jcBOXFG],jwin_pal[jcBOX],0);
1528 for(int q = 0; q < XMODE_MAX; ++q)
1529 {
1530 auto& sqr = xmodebtn_grid.subsquare(q);
1531 draw_text_button(screen2,sqr.x,sqr.y,sqr.w,sqr.h,xmodebtn_names[q],vc(1),vc(14),(xmode == q) ? D_SELECTED : 0,true);
1532 }
1533 for(int q = 0; q < BGMODE_MAX; ++q)
1534 {
1535 auto& sqr = bgmodebtn_grid.subsquare(q);
1536 draw_text_button(screen2,sqr.x,sqr.y,sqr.w,sqr.h,bgmodebtn_names[q],vc(1),vc(14),(bgmode == q) ? D_SELECTED : 0,true);
1537 }
1538
1539 //tool buttons
1540 for(int32_t toolbtn = 0; toolbtn < t_max; ++toolbtn)
1541 {
1542 auto bmp = toolbtn+MOUSE_BMP_SWORD;
1543 int col = toolbtn%tool_btns.w;
1544 int row = toolbtn/tool_btns.w;
1545
1546 jwin_draw_button(screen2,tool_btns.x+(col*tool_btns.xscale),tool_btns.y+(row*tool_btns.yscale),tool_btns.xscale,tool_btns.yscale,tool==toolbtn?2:0,0);
1547 masked_stretch_blit(mouse_bmp_1x[bmp][0],screen2,0,0,16,16,tool_btns.x+(col*tool_btns.xscale)+3+(tool==toolbtn?1:0),tool_btns.y+3+(row*tool_btns.yscale)+(tool==toolbtn?1:0),tool_btns.xscale-7,tool_btns.yscale-7);
1548 }
1549
1550 //coordinates
1551 {
1552 auto mx = gui_mouse_x();
1553 auto my = gui_mouse_y();
1554 int32_t ind = zoomtile.rectind(mx,my);
1555 int32_t temp_x=ind%zoomtile.w;
1556 int32_t temp_y=ind/zoomtile.w;
1557 int color = -1;
1558
1559 bool is8b = newtilebuf[tile].format > tf4Bit;
1560 if(ind > -1)
1561 {
1562 char xbuf[16];
1563 sprintf(xbuf, "x: %d", temp_x);
1564 textprintf_ex(screen2,font,status_info.x,status_info.y+(3*status_info.yscale),jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%s",xbuf);
1565 textprintf_ex(screen2,font,status_info.x+text_length(font,xbuf)+8,status_info.y+(3*status_info.yscale),jwin_pal[jcBOXFG],jwin_pal[jcBOX],"y: %d",temp_y);
1566 unpack_tile(newtilebuf, tile, 0, false);
1567 byte *si = unpackbuf;
1568 si+=ind;
1569 color = *si;
1570 }
1571 else if(fg_prev.rect(mx,my))
1572 color = c1;
1573 else if(bg_prev.rect(mx,my))
1574 color = c2;
1575 else color = (is8b ? cpalette_8 : cpalette_4).rectind(mx,my);
1576 if(color > -1)
1577 {
1578 get_palette(tpal);
1579 char separator = ' ';
1580 char buf[512] = {0};
1581
1582 int realcol = color+(is8b?0:CSET(cs));
1583 bool xcolor = (is8b ? realcol == 0 : (realcol%16)==0);
1584 auto& c = tpal[realcol];
1585
1586 if(tthighlight)
1587 {
1588 size_and_pos const& mainsqr = is8b ? cpalette_8 : cpalette_4;
1589 size_and_pos const& csqr = mainsqr.subsquare(color);
1590
1591 int hlcol = getHighlightColor(tpal[realcol]);
1592 int hlthick = 4;
1593 int extraborder = is8b ? 8 : 0;
1594 int borderthick = hlthick+extraborder;
1595
1596 if(is8b)
1597 {
1598 highlight_sqr(screen2, 0xED, csqr.x, mainsqr.y, csqr.w, mainsqr.h*mainsqr.yscale, hlthick); //column
1599 highlight_sqr(screen2, 0xED, mainsqr.x, csqr.y, mainsqr.w*mainsqr.xscale, csqr.h, hlthick); //row
1600 }
1601 highlight_sqr(screen2, 0xED, csqr.x-borderthick, csqr.y-borderthick, csqr.w+borderthick*2, csqr.h+borderthick*2, hlthick); //square hl
1602 rectfill(screen2, csqr.x-extraborder, csqr.y-extraborder, csqr.x+csqr.w-1+extraborder, csqr.y+csqr.h-1+extraborder, realcol); //square color
1603 if(xcolor)
1604 little_x(screen2, csqr.x-extraborder+4, csqr.y-extraborder+4, invcol, csqr.w+(extraborder*2)-8, csqr.h+(extraborder*2)-8); //transparent X
1605 highlight_sqr(screen2, hlcol, csqr.x-extraborder, csqr.y-extraborder, csqr.w+extraborder*2, csqr.h+extraborder*2, 1); //highlight border
1606 }
1607
1608 sprintf(buf, "%02d %02d %02d %c(0x%02X %d)",c.r,c.g,c.b,separator,realcol,color);
1609 gui_textout_ln(screen2,font,(unsigned char*)buf,hover_info.x,hover_info.y+(2*hover_info.yscale),jwin_pal[jcBOXFG],jwin_pal[jcBOX],0);
1610
1611 strcpy(buf, get_color_name(realcol, is8b).c_str());
1612 gui_textout_ln(screen2,font,(unsigned char*)buf,hover_info.x,hover_info.y+(1*hover_info.yscale),jwin_pal[jcBOXFG],jwin_pal[jcBOX],0);
1613
1614 sprintf(buf, "#%02X%02X%02X", tpal[realcol].r,tpal[realcol].g,tpal[realcol].b);
1615 gui_textout_ln(screen2,font,(unsigned char*)buf,hover_info.x,hover_info.y+(0),jwin_pal[jcBOXFG],jwin_pal[jcBOX],0);
1616
1617 rect(screen2, hov_prev.x, hov_prev.y, hov_prev.x+hov_prev.w-1, hov_prev.y+hov_prev.h-1, jwin_pal[jcTEXTFG]);
1618 rectfill(screen2, hov_prev.x+1, hov_prev.y+1, hov_prev.x+hov_prev.w-2, hov_prev.y+hov_prev.h-2, jwin_pal[jcTEXTBG]);
1619 rectfill(screen2, hov_prev.x+3, hov_prev.y+3, hov_prev.x+hov_prev.w-4, hov_prev.y+hov_prev.h-4, realcol);
1620 if(xcolor)
1621 little_x(screen2, hov_prev.x+1, hov_prev.y+1, invcol, hov_prev.w-2, hov_prev.h-2);
1622 }
1623 }
1624
1625 custom_vsync();
1626 blit(screen2,screen,0,0,0,0,zq_screen_w,zq_screen_w);
1627 update_tool_cursor();
1628 SCRFIX();
1629 }
1630
1631 void normalize(int32_t tile,int32_t tile2, bool rect_sel, int32_t flip)
1632 {
1633 unfloat_selection();
1634 if(tile>tile2)
1635 {
1636 zc_swap(tile, tile2);
1637 }
1638
1639 int32_t left=zc_min(TILECOL(tile), TILECOL(tile2));
1640 int32_t columns=zc_max(TILECOL(tile), TILECOL(tile2))-left+1;
1641
1642 int32_t start=tile;
1643 int32_t end=tile2;
1644
1645 // Might have top-right and bottom-left corners selected...
1646 if(rect_sel && TILECOL(tile)>TILECOL(tile2))
1647 {
1648 start=tile-(TILECOL(tile)-TILECOL(tile2));
1649 end=tile2+(TILECOL(tile)-TILECOL(tile2));
1650 }
1651
1652 for(int32_t temptile=start; temptile<=end; temptile++)
1653 {
1654 if(!rect_sel || ((TILECOL(temptile)>=left) && (TILECOL(temptile)<=left+columns-1)))
1655 {
1656 unpack_tile(newtilebuf, temptile, 0, true);
1657
1658 if(flip&1)
1659 {
1660 for(int32_t y=0; y<16; y++)
1661 {
1662 for(int32_t x=0; x<8; x++)
1663 {
1664 zc_swap(unpackbuf[(y<<4)+x],unpackbuf[(y<<4)+15-x]);
1665 }
1666 }
1667 }
1668
1669 if(flip&2)
1670 {
1671 for(int32_t y=0; y<8; y++)
1672 {
1673 for(int32_t x=0; x<16; x++)
1674 {
1675 zc_swap(unpackbuf[(y<<4)+x],unpackbuf[((15-y)<<4)+x]);
1676 }
1677 }
1678 }
1679
1680 pack_tile(newtilebuf,unpackbuf,temptile);
1681 }
1682 }
1683 }
1684
1685 void rotate_tile(int32_t tile, bool backward)
1686 {
1687 unfloat_selection();
1688 unpack_tile(newtilebuf, tile, 0, true);
1689 byte tempunpackbuf[256];
1690 byte tempx, tempy;
1691
1692 for(tempx=0; tempx<16; tempx++)
1693 {
1694 for(tempy=0; tempy<16; tempy++)
1695 {
1696 if(!backward)
1697 {
1698 tempunpackbuf[(tempy<<4)+tempx]=unpackbuf[((15-tempx)<<4)+tempy];
1699 }
1700 else
1701 {
1702 tempunpackbuf[((15-tempx)<<4)+tempy]=unpackbuf[(tempy<<4)+tempx];
1703 }
1704 }
1705 }
1706
1707 pack_tile(newtilebuf,tempunpackbuf,tile);
1708 }
1709
1710 static int32_t undocount=128;
1711 byte undotile[256];
1712
1713 void wrap_tile(int32_t tile, int32_t vertical, int32_t horizontal, bool clear)
1714 {
1715 byte buf[256];
1716
1717 for(int32_t i=0; i<undocount; i++)
1718 {
1719 newtilebuf[tile].data[i]=undotile[i];
1720 }
1721
1722 if(!(horizontal||vertical))
1723 {
1724 return;
1725 }
1726
1727 unpack_tile(newtilebuf, tile, 0, true);
1728
1729 for(int32_t i=0; i<256; i++)
1730 {
1731 auto shift_ind = ((i+horizontal)&0x0F)|((i+(vertical*0x10))&0xF0);
1732 buf[shift_ind] = unpackbuf[i];
1733 }
1734
1735 if(clear)
1736 {
1737 for(int32_t r=0; r<abs(vertical); r++)
1738 {
1739 for(int32_t c=0; c<16; c++)
1740 {
1741 buf[(vertical>0?r:15-r)*16+c]=0;
1742 }
1743 }
1744
1745 for(int32_t r=0; r<16; r++)
1746 {
1747 for(int32_t c=0; c<abs(horizontal); c++)
1748 {
1749 buf[r*16+(horizontal>0?c:15-c)]=0;
1750 }
1751 }
1752 }
1753
1754 pack_tile(newtilebuf,buf,tile);
1755 }
1756
1757 void wrap_sel_tile(int32_t vertical, int32_t horizontal)
1758 {
1759 byte buf[256];
1760
1761 if(!(horizontal||vertical))
1762 {
1763 return;
1764 }
1765
1766 memset(buf,0,256);
1767
1768 for(int32_t i=0; i<256; i++)
1769 {
1770 if(is_in_selection(i%16,i/16))
1771 {
1772 auto shift_ind = ((i+horizontal)&0x0F)|((i+(vertical*0x10))&0xF0);
1773 buf[shift_ind] = floatsel[i];
1774 }
1775 }
1776
1777 memcpy(floatsel,buf,256);
1778 }
1779
1780 void float_selection(int32_t tile, bool clear)
1781 {
1782 if(floating_sel) return;
1783 floating_sel = true;
1784 floating_tile = tile;
1785
1786 unpack_tile(newtilebuf, tile, 0, true);
1787
1788 for(auto q = 0; q < 256; ++q)
1789 {
1790 if(is_in_selection(q%16,q/16))
1791 {
1792 floatsel[q] = unpackbuf[q];
1793 unpackbuf[q] = clear ? 0 : c2;
1794 }
1795 else floatsel[q] = 0;
1796 }
1797
1798 pack_tile(newtilebuf,unpackbuf,tile);
1799 }
1800
1801 void unfloat_selection()
1802 {
1803 if(!floating_sel) return;
1804 floating_sel = false;
1805
1806 unpack_tile(newtilebuf, floating_tile, 0, true);
1807
1808 for(auto q = 0; q < 256; ++q)
1809 {
1810 if(floatsel[q])
1811 {
1812 unpackbuf[q] = floatsel[q];
1813 }
1814 }
1815
1816 pack_tile(newtilebuf,unpackbuf,floating_tile);
1817 floating_tile = -1;
1818 }
1819
1820 void shift_tile_colors(int32_t tile, int32_t amount, bool ignore_transparent)
1821 {
1822 if(floating_sel)
1823 {
1824 for(auto q = 0; q < 256; ++q)
1825 {
1826 if(ignore_transparent && floatsel[q]==0)
1827 continue;
1828 floatsel[q]=wrap(floatsel[q]+amount, 0, newtilebuf[tile].format==tf8Bit ? 0xDF : 0xF);
1829 }
1830 return;
1831 }
1832
1833 byte buf[256];
1834 unpack_tile(newtilebuf, tile, 0, true);
1835
1836 for(int32_t i=0; i<256; i++)
1837 {
1838 buf[i]=unpackbuf[i];
1839
1840 if(!is_in_selection(i&0x0F, (i&0xF0)>>4))
1841 continue;
1842
1843 if(ignore_transparent)
1844 {
1845 if(buf[i]==0)
1846 continue;
1847
1848 buf[i]=wrap(buf[i]+amount, 1, newtilebuf[tile].format==tf8Bit ? 0xDF : 0xF);
1849 }
1850 else // Don't ignore transparent
1851 buf[i]=wrap(buf[i]+amount, 0, newtilebuf[tile].format==tf8Bit ? 0xDF : 0xF);
1852 }
1853
1854 pack_tile(newtilebuf,buf,tile);
1855 }
1856
1857 void clear_selection_grid()
1858 {
1859 unfloat_selection();
1860 for(int32_t x=0; x<18; ++x)
1861 {
1862 for(int32_t y=0; y<18; ++y)
1863 {
1864 selection_grid[x][y]=0;
1865 }
1866 }
1867 }
1868
1869 void invert_selection_grid()
1870 {
1871 unfloat_selection();
1872 for(int32_t x=1; x<17; ++x)
1873 {
1874 for(int32_t y=1; y<17; ++y)
1875 {
1876 selection_grid[x][y]=selection_grid[x][y]?0:1;
1877 }
1878 }
1879 }
1880
1881 void shift_selection_grid(int32_t xoffs, int32_t yoffs)
1882 {
1883 byte local_grid[16][16];
1884 memset(local_grid, 0, sizeof(local_grid));
1885 for(auto x = 0; x < 16; ++x)
1886 {
1887 for(auto y = 0; y < 16; ++y)
1888 {
1889 auto offs_x = (x+xoffs)%16, offs_y = (y+yoffs)%16;
1890 if(offs_x < 0) offs_x = (16 - abs(offs_x));
1891 if(offs_y < 0) offs_y = (16 - abs(offs_y));
1892 local_grid[offs_x][offs_y] = selection_grid[x+1][y+1]?1:0;
1893 }
1894 }
1895 for(auto x = 0; x < 16; ++x)
1896 {
1897 for(auto y = 0; y < 16; ++y)
1898 {
1899 selection_grid[x+1][y+1] = local_grid[x][y]?1:0;
1900 }
1901 }
1902 }
1903
1904 void show_edit_tile_help()
1905 {
1906 InfoDialog("Help: Tile Editor", "Hotkeys:"
1907 "\nF1: This Help Dialog"
1908 "\nEnter: Unfloat Sel / OK | Esc: Unfloat Sel / Cancel"
1909 "\nDelete: Clear Tile/Sel | Ctrl+Delete: Clear Tile"
1910 "\nA: Sel All | D: Unselect Sel | I: Invert Sel"
1911 "\nH/V: Flip | (Shift+)R: Rotate"
1912 "\n+/-: Change CSet | Ctrl +/-: Shift Colors"
1913 "\n(Ctrl+)S: Swap Colors | U/Ctrl+Z: Undo"
1914 "\nF12: Screenshot (whole screen)"
1915 "\nArrows: Shift Pixel | Ctrl+Arrows: Change Tile"
1916 "\nWhen not on Select tools, hold to swap:"
1917 "\nCtrl - Fill | Alt - Grab | Ctrl+Alt - Recolor").show();
1918 }
1919
1920 static int move_origin_x=-1, move_origin_y=-1;
1921 static int prev_x=-1, prev_y=-1;
1922 bool __pixel_draw(int x, int y, int tile, int flip)
1923 {
1924 bool ret = false;
1925 switch(tool)
1926 {
1927 case t_pen:
1928 if(flip&1) x=15-x;
1929
1930 if(flip&2) y=15-y;
1931
1932 if(is_in_selection(x,y))
1933 {
1934 if(floating_sel)
1935 {
1936 floatsel[(y<<4)+x]=(drawing==1)?c1:c2;
1937 }
1938 else
1939 {
1940 unpack_tile(newtilebuf, tile, 0, false);
1941 unpackbuf[((y<<4)+x)]=(drawing==1)?c1:c2;
1942 pack_tile(newtilebuf, unpackbuf,tile);
1943 }
1944 }
1945 break;
1946
1947 case t_fill:
1948 if(is_in_selection(x,y))
1949 {
1950 tile_floodfill(tile,x,y,(drawing==1)?c1:c2);
1951 ret = true;
1952 }
1953 break;
1954
1955 case t_recolor:
1956 if(is_in_selection(x,y))
1957 {
1958 if(floating_sel)
1959 {
1960 tf_u = floatsel[(y<<4)+x];
1961 for(int32_t i=0; i<256; i++)
1962 {
1963 if(is_in_selection(i&15,i>>4))
1964 {
1965 if(floatsel[i]==tf_u)
1966 {
1967 floatsel[i]=(drawing==1)?c1:c2;
1968 }
1969 }
1970 }
1971 }
1972 else
1973 {
1974 unpack_tile(newtilebuf, tile, 0, false);
1975 tf_u = unpackbuf[(y<<4)+x];
1976 if(tf_u != ((drawing==1)?c1:c2))
1977 {
1978 for(int32_t i=0; i<256; i++)
1979 {
1980 if(is_in_selection(i&15,i>>4))
1981 {
1982 if(unpackbuf[i]==tf_u)
1983 {
1984 unpackbuf[i]=(drawing==1)?c1:c2;
1985 }
1986 }
1987 }
1988
1989 pack_tile(newtilebuf, unpackbuf,tile);
1990 }
1991 }
1992 ret = true;
1993 }
1994 break;
1995
1996 case t_eyedropper:
1997 if(floating_sel)
1998 memcpy(unpackbuf, floatsel, 256);
1999 else unpack_tile(newtilebuf, tile, 0, false);
2000
2001 if(gui_mouse_b()&1)
2002 {
2003 c1=unpackbuf[((y<<4)+x)];
2004 }
2005
2006 if(gui_mouse_b()&2)
2007 {
2008 c2=unpackbuf[((y<<4)+x)];
2009 }
2010 break;
2011
2012 case t_move:
2013 if((prev_x!=x)||(prev_y!=y))
2014 {
2015 if(has_selection())
2016 {
2017 float_selection(tile,key[KEY_LSHIFT]||key[KEY_RSHIFT]);
2018 wrap_sel_tile(y-prev_y, x-prev_x);
2019 shift_selection_grid(x-prev_x, y-prev_y);
2020 }
2021 else wrap_tile(tile, y-move_origin_y, x-move_origin_x, drawing==2);
2022 prev_x=x;
2023 prev_y=y;
2024 }
2025 break;
2026
2027 case t_select:
2028 unfloat_selection();
2029 if(flip&1) x=15-x;
2030
2031 if(flip&2) y=15-y;
2032
2033 if(selecting_x1==-1||selecting_y1==-1)
2034 {
2035 selecting_x1=x;
2036 selecting_y1=y;
2037 }
2038 else
2039 {
2040 selecting_x2=x;
2041 selecting_y2=y;
2042 }
2043 break;
2044
2045 case t_wand:
2046 unfloat_selection();
2047 if(flip&1) x=15-x;
2048
2049 if(flip&2) y=15-y;
2050
2051 switch(select_mode)
2052 {
2053 case 0:
2054 clear_selection_grid();
2055 add_color_to_selection(unpackbuf[((y<<4)+x)]);
2056 break;
2057
2058 case 1:
2059 add_color_to_selection(unpackbuf[((y<<4)+x)]);
2060 break;
2061
2062 case 2:
2063 remove_color_from_selection(unpackbuf[((y<<4)+x)]);
2064 break;
2065
2066 case 3:
2067 intersect_color_with_selection(unpackbuf[((y<<4)+x)]);
2068 break;
2069 }
2070
2071 ret = true;
2072 break;
2073 }
2074 return ret;
2075 }
2076 void edit_tile(int32_t tile,int32_t flip,int32_t &cs)
2077 {
2078 popup_zqdialog_start();
2079 FONT* oldfont = font;
2080 font = get_custom_font(CFONT_DLG);
2081 edit_button.h = ok_button.h = cancel_button.h = 12+text_height(font);
2082 status_info.yscale = text_height(font);
2083 status_info.y = 308-(status_info.h*status_info.yscale);
2084 hover_info.yscale = status_info.yscale;
2085 hover_info.y = 338-(hover_info.h*hover_info.yscale);
2086 go();
2087 undocount = tilesize(newtilebuf[tile].format);
2088 clear_selection_grid();
2089 selecting_x1=selecting_x2=selecting_y1=selecting_y2=-1;
2090
2091 tthighlight = zc_get_config("ZQ_GUI","tile_edit_fancyhighlight",1);
2092 showcolortip = zc_get_config("ZQ_GUI","tile_edit_colornames",1);
2093
2094 PALETTE tpal;
2095 byte oldtile[256];
2096
2097 memset(&tpal, 0, sizeof(PALETTE));
2098 memset(oldtile, 0, 256);
2099
2100 for(int32_t i=0; i<undocount; i++)
2101 {
2102 oldtile[i]=undotile[i]=newtilebuf[tile].data[i];
2103 }
2104 byte undoselgrid[16][16];
2105 for(auto x = 0; x < 16; ++x)
2106 for(auto y = 0; y < 16; ++y)
2107 undoselgrid[x][y] = selection_grid[x+1][y+1];
2108 for(auto q = 0; q < 256; ++q)
2109 {
2110 floatsel[q] = 0;
2111 undofloatsel[q] = 0;
2112 floating_sel = false;
2113 undo_is_floatsel = false;
2114 }
2115
2116 int32_t tile_x=-1, tile_y=-1;
2117 int32_t temp_x=-1, temp_y=-1;
2118 bool bdown=false;
2119 int32_t done=0;
2120 drawing=0;
2121 tool_cur = -1;
2122
2123 get_palette(tpal);
2124
2125 if(newtilebuf[tile].format==tf4Bit)
2126 {
2127 invcol=makecol8(255 - tpal[CSET(cs)].r, 255 - tpal[CSET(cs)].g, 255 - tpal[CSET(cs)].b);
2128 }
2129 else
2130 {
2131 invcol=makecol8(255 - tpal[0].r, 255 - tpal[0].g, 255 - tpal[0].b);
2132 }
2133
2134 custom_vsync();
2135 zc_set_palette(tpal);
2136 draw_edit_scr(tile,flip,cs,oldtile, true);
2137
2138 while(gui_mouse_b())
2139 {
2140 /* do nothing */
2141 rest(1);
2142 }
2143
2144 move_origin_x=-1;
2145 move_origin_y=-1;
2146 prev_x=-1;
2147 prev_y=-1;
2148
2149
2150
2151 byte selection_pattern_source[8][8]=
2152 {
2153 {1, 1, 1, 1, 0, 0, 0, 0},
2154 {1, 1, 1, 0, 0, 0, 0, 1},
2155 {1, 1, 0, 0, 0, 0, 1, 1},
2156 {1, 0, 0, 0, 0, 1, 1, 1},
2157 {0, 0, 0, 0, 1, 1, 1, 1},
2158 {0, 0, 0, 1, 1, 1, 1, 0},
2159 {0, 0, 1, 1, 1, 1, 0, 0},
2160 {0, 1, 1, 1, 1, 0, 0, 0},
2161 };
2162
2163 byte selecting_pattern_source[8][8]=
2164 {
2165 {1, 1, 0, 0, 0, 0, 1, 1},
2166 {1, 0, 0, 0, 0, 1, 1, 1},
2167 {0, 0, 0, 0, 1, 1, 1, 1},
2168 {0, 0, 0, 1, 1, 1, 1, 0},
2169 {0, 0, 1, 1, 1, 1, 0, 0},
2170 {0, 1, 1, 1, 1, 0, 0, 0},
2171 {1, 1, 1, 1, 0, 0, 0, 0},
2172 {1, 1, 1, 0, 0, 0, 0, 1},
2173 };
2174
2175 byte intersection_pattern_source[8][8]=
2176 {
2177 {0, 0, 1, 1, 0, 0, 1, 1},
2178 {0, 1, 1, 0, 0, 1, 1, 0},
2179 {1, 1, 0, 0, 1, 1, 0, 0},
2180 {1, 0, 0, 1, 1, 0, 0, 1},
2181 {0, 0, 1, 1, 0, 0, 1, 1},
2182 {0, 1, 1, 0, 0, 1, 1, 0},
2183 {1, 1, 0, 0, 1, 1, 0, 0},
2184 {1, 0, 0, 1, 1, 0, 0, 1},
2185 };
2186
2187 selection_pattern=create_bitmap_ex(8, 8, 8);
2188
2189 for(int32_t x=0; x<8; ++x)
2190 {
2191 for(int32_t y=0; y<8; ++y)
2192 {
2193 selection_pattern->line[y][x]=selection_pattern_source[x][y]?vc(0):vc(15);
2194 }
2195 }
2196
2197 selecting_pattern=create_bitmap_ex(8, 8, 8);
2198
2199 for(int32_t x=0; x<8; ++x)
2200 {
2201 for(int32_t y=0; y<8; ++y)
2202 {
2203 selecting_pattern->line[y][x]=selecting_pattern_source[x][y]?vc(0):vc(15);
2204 }
2205 }
2206
2207 intersection_pattern=create_bitmap_ex(8, 8, 8);
2208
2209 for(int32_t x=0; x<8; ++x)
2210 {
2211 for(int32_t y=0; y<8; ++y)
2212 {
2213 intersection_pattern->line[y][x]=intersection_pattern_source[x][y]?vc(0):vc(15);
2214 }
2215 }
2216
2217 do
2218 {
2219 HANDLE_CLOSE_ZQDLG();
2220 if(exiting_program) break;
2221 int32_t temp_mouse_x=gui_mouse_x();
2222 int32_t temp_mouse_y=gui_mouse_y();
2223 rest(4);
2224 bool redraw=false;
2225 bool did_wand_select=false;
2226
2227 if(keypressed())
2228 {
2229 bool ctrl = CHECK_CTRL_CMD;
2230 int k = readkey()>>8;
2231 switch(k)
2232 {
2233 case KEY_F1:
2234 show_edit_tile_help();
2235 break;
2236 case KEY_ENTER_PAD:
2237 case KEY_ENTER:
2238 if(floating_sel)
2239 unfloat_selection();
2240 else done=2;
2241 break;
2242
2243 case KEY_ESC:
2244 if(floating_sel)
2245 unfloat_selection();
2246 else if(has_selection())
2247 clear_selection_grid();
2248 else done=1;
2249 break;
2250
2251 case KEY_DEL:
2252 {
2253 unpack_tile(newtilebuf, tile, 0, false);
2254 bool all = CHECK_CTRL_CMD || !has_selection();
2255 bool canDel = false;
2256 if(all)
2257 {
2258 //Check all
2259 for(auto q = 0; q < 256; ++q)
2260 if(unpackbuf[q])
2261 {
2262 canDel = true;
2263 break;
2264 }
2265 }
2266 else
2267 {
2268 //Check selection
2269 for(auto x = 0; x < 16; ++x)
2270 for(auto y = 0; y < 16; ++y)
2271 if(is_in_selection(x,y))
2272 if(unpackbuf[(y<<4)+x])
2273 {
2274 canDel = true;
2275 break;
2276 }
2277 }
2278 if(!canDel) break; //don't delete (and thus reset undo) if nothing would change!
2279
2280 for(int32_t i=0; i<undocount; i++)
2281 {
2282 undotile[i]=newtilebuf[tile].data[i];
2283 }
2284 for(auto x = 0; x < 16; ++x)
2285 for(auto y = 0; y < 16; ++y)
2286 undoselgrid[x][y] = selection_grid[x+1][y+1];
2287 for(auto q = 0; q < 256; ++q)
2288 undofloatsel[q] = floatsel[q];
2289 undo_is_floatsel = floating_sel;
2290
2291 if(CHECK_CTRL_CMD || !has_selection())
2292 {
2293 //Delete all
2294 for(auto q = 0; q < 256; ++q)
2295 {
2296 unpackbuf[q] = 0;
2297 floatsel[q] = 0;
2298 }
2299 }
2300 else
2301 {
2302 //Delete selection
2303 for(auto x = 0; x < 16; ++x)
2304 for(auto y = 0; y < 16; ++y)
2305 {
2306 if(floating_sel)
2307 {
2308 floatsel[x+(y<<4)] = 0;
2309 }
2310 else if(is_in_selection(x,y))
2311 {
2312 unpackbuf[(y<<4)+x] = 0;
2313 }
2314 }
2315 }
2316 pack_tile(newtilebuf, unpackbuf, tile);
2317 redraw=true;
2318 }
2319 break;
2320
2321 case KEY_A:
2322 clear_selection_grid();
2323 invert_selection_grid();
2324 redraw=true;
2325 break;
2326
2327 case KEY_D:
2328 clear_selection_grid();
2329 redraw=true;
2330 break;
2331
2332 case KEY_I:
2333 invert_selection_grid();
2334 redraw=true;
2335 break;
2336
2337 case KEY_H:
2338 flip^=1;
2339 normalize(tile,tile,0,flip);
2340 flip=0;
2341 redraw=true;
2342 break;
2343
2344 case KEY_V:
2345 flip^=2;
2346 normalize(tile,tile,0,flip);
2347 flip=0;
2348 redraw=true;
2349 break;
2350
2351 case KEY_F12:
2352 onSnapshot();
2353 break;
2354
2355 case KEY_R:
2356 {
2357 //if(CHECK_CTRL_CMD))
2358 // {
2359 //do_recolor(tile); redraw=true; saved=false;
2360 // }
2361 //else
2362 // {
2363 go_tiles();
2364 rotate_tile(tile,(key[KEY_LSHIFT] || key[KEY_RSHIFT]));
2365 redraw=true;
2366 saved=false;
2367 break;
2368 }
2369
2370 case KEY_EQUALS:
2371 case KEY_PLUS_PAD:
2372 {
2373 if(CHECK_CTRL_CMD ||
2374 key[KEY_ALT] || key[KEY_ALTGR])
2375 {
2376 for(int32_t i=0; i<undocount; i++)
2377 undotile[i]=newtilebuf[tile].data[i];
2378 for(auto x = 0; x < 16; ++x)
2379 for(auto y = 0; y < 16; ++y)
2380 undoselgrid[x][y] = selection_grid[x+1][y+1];
2381 for(auto q = 0; q < 256; ++q)
2382 undofloatsel[q] = floatsel[q];
2383 undo_is_floatsel = floating_sel;
2384
2385 if(key[KEY_ALT] || key[KEY_ALTGR])
2386 shift_tile_colors(tile, 16, false);
2387 else
2388 shift_tile_colors(tile, 1, key[KEY_LSHIFT] || key[KEY_RSHIFT]);
2389 }
2390 else
2391 cs = (cs<13) ? cs+1:0;
2392
2393 redraw=true;
2394 break;
2395 }
2396
2397 case KEY_MINUS:
2398 case KEY_MINUS_PAD:
2399 {
2400 if(CHECK_CTRL_CMD ||
2401 key[KEY_ALT] || key[KEY_ALTGR])
2402 {
2403 for(int32_t i=0; i<undocount; i++)
2404 undotile[i]=newtilebuf[tile].data[i];
2405 for(auto x = 0; x < 16; ++x)
2406 for(auto y = 0; y < 16; ++y)
2407 undoselgrid[x][y] = selection_grid[x+1][y+1];
2408 for(auto q = 0; q < 256; ++q)
2409 undofloatsel[q] = floatsel[q];
2410 undo_is_floatsel = floating_sel;
2411
2412 if(key[KEY_ALT] || key[KEY_ALTGR])
2413 shift_tile_colors(tile, -16, false);
2414 else
2415 shift_tile_colors(tile, -1, key[KEY_LSHIFT] || key[KEY_RSHIFT]);
2416 }
2417 else
2418 cs = (cs>0) ? cs-1:13;
2419
2420 redraw=true;
2421 break;
2422 }
2423
2424 case KEY_SPACE:
2425 gridmode=(gridmode+1)%gm_max;
2426 redraw=true;
2427 break;
2428
2429 case KEY_Z:
2430 if(!ctrl)
2431 break;
2432 //Ctrl+Z == undo
2433 [[fallthrough]];
2434 case KEY_U:
2435 for(int32_t i=0; i<undocount; i++)
2436 zc_swap(undotile[i],newtilebuf[tile].data[i]);
2437
2438 for(auto x = 0; x < 16; ++x)
2439 for(auto y = 0; y < 16; ++y)
2440 zc_swap(selection_grid[x+1][y+1], undoselgrid[x][y]);
2441
2442 for(auto q = 0; q < 256; ++q)
2443 zc_swap(undofloatsel[q], floatsel[q]);
2444 zc_swap(undo_is_floatsel, floating_sel);
2445
2446 redraw=true;
2447 break;
2448
2449 case KEY_S:
2450 if(CHECK_CTRL_CMD)
2451 {
2452 for(int32_t i=0; i<undocount; i++)
2453 {
2454 undotile[i]=newtilebuf[tile].data[i];
2455 }
2456 for(auto x = 0; x < 16; ++x)
2457 for(auto y = 0; y < 16; ++y)
2458 undoselgrid[x][y] = selection_grid[x+1][y+1];
2459 for(auto q = 0; q < 256; ++q)
2460 undofloatsel[q] = floatsel[q];
2461 undo_is_floatsel = floating_sel;
2462
2463 unpack_tile(newtilebuf, tile, 0, false);
2464
2465 if(has_selection())
2466 {
2467 for(int32_t i=0; i<256; i++)
2468 {
2469 if(!is_in_selection(i%16,i/16))
2470 continue;
2471 if(unpackbuf[i]==c1)
2472 {
2473 unpackbuf[i]=c2;
2474 }
2475 else if(unpackbuf[i]==c2)
2476 {
2477 unpackbuf[i]=c1;
2478 }
2479 if(floating_sel)
2480 {
2481 if(floatsel[i]==c1)
2482 {
2483 floatsel[i]=c2;
2484 }
2485 else if(floatsel[i]==c2)
2486 {
2487 floatsel[i]=c1;
2488 }
2489 }
2490 }
2491 }
2492 else
2493 {
2494 for(int32_t i=0; i<256; i++)
2495 {
2496 if(unpackbuf[i]==c1)
2497 {
2498 unpackbuf[i]=c2;
2499 }
2500 else if(unpackbuf[i]==c2)
2501 {
2502 unpackbuf[i]=c1;
2503 }
2504 }
2505 }
2506
2507 pack_tile(newtilebuf, unpackbuf,tile);
2508 }
2509
2510 zc_swap(c1,c2);
2511 redraw=true;
2512 break;
2513
2514 case KEY_UP:
2515 if(CHECK_CTRL_CMD)
2516 {
2517 unfloat_selection();
2518 tile=zc_max(0,tile-TILES_PER_ROW);
2519 undocount = tilesize(newtilebuf[tile].format);
2520
2521 for(int32_t i=0; i<undocount; i++)
2522 {
2523 undotile[i]=newtilebuf[tile].data[i];
2524 oldtile[i]=undotile[i];
2525 }
2526
2527 redraw=true;
2528 }
2529 else
2530 {
2531 for(int32_t i=0; i<undocount; i++)
2532 {
2533 undotile[i]=newtilebuf[tile].data[i];
2534 }
2535 for(auto x = 0; x < 16; ++x)
2536 for(auto y = 0; y < 16; ++y)
2537 undoselgrid[x][y] = selection_grid[x+1][y+1];
2538 for(auto q = 0; q < 256; ++q)
2539 undofloatsel[q] = floatsel[q];
2540 undo_is_floatsel = floating_sel;
2541 if(has_selection())
2542 {
2543 float_selection(tile,key[KEY_LSHIFT]||key[KEY_RSHIFT]);
2544 wrap_sel_tile(-1, 0);
2545 shift_selection_grid(0, -1);
2546 }
2547 else wrap_tile(tile, -1, 0, false);
2548 redraw=true;
2549 }
2550 break;
2551
2552 case KEY_DOWN:
2553 if(CHECK_CTRL_CMD)
2554 {
2555 unfloat_selection();
2556 tile=zc_min(tile+TILES_PER_ROW,NEWMAXTILES-1);
2557 undocount = tilesize(newtilebuf[tile].format);
2558
2559 for(int32_t i=0; i<undocount; i++)
2560 {
2561 undotile[i]=newtilebuf[tile].data[i];
2562 oldtile[i]=undotile[i];
2563 }
2564
2565 redraw=true;
2566 }
2567 else
2568 {
2569 for(int32_t i=0; i<undocount; i++)
2570 {
2571 undotile[i]=newtilebuf[tile].data[i];
2572 }
2573 for(auto x = 0; x < 16; ++x)
2574 for(auto y = 0; y < 16; ++y)
2575 undoselgrid[x][y] = selection_grid[x+1][y+1];
2576 for(auto q = 0; q < 256; ++q)
2577 undofloatsel[q] = floatsel[q];
2578 undo_is_floatsel = floating_sel;
2579 if(has_selection())
2580 {
2581 float_selection(tile,key[KEY_LSHIFT]||key[KEY_RSHIFT]);
2582 wrap_sel_tile(1, 0);
2583 shift_selection_grid(0, 1);
2584 }
2585 else wrap_tile(tile, 1, 0, false);
2586 redraw=true;
2587 }
2588 break;
2589
2590 case KEY_LEFT:
2591 if(CHECK_CTRL_CMD)
2592 {
2593 unfloat_selection();
2594 tile=zc_max(0,tile-1);
2595 undocount = tilesize(newtilebuf[tile].format);
2596
2597 for(int32_t i=0; i<undocount; i++)
2598 {
2599 undotile[i]=newtilebuf[tile].data[i];
2600 oldtile[i]=undotile[i];
2601 }
2602
2603 redraw=true;
2604 }
2605 else
2606 {
2607 for(int32_t i=0; i<undocount; i++)
2608 {
2609 undotile[i]=newtilebuf[tile].data[i];
2610 }
2611 for(auto x = 0; x < 16; ++x)
2612 for(auto y = 0; y < 16; ++y)
2613 undoselgrid[x][y] = selection_grid[x+1][y+1];
2614 for(auto q = 0; q < 256; ++q)
2615 undofloatsel[q] = floatsel[q];
2616 undo_is_floatsel = floating_sel;
2617 if(has_selection())
2618 {
2619 float_selection(tile,key[KEY_LSHIFT]||key[KEY_RSHIFT]);
2620 wrap_sel_tile(0, -1);
2621 shift_selection_grid(-1, 0);
2622 }
2623 else wrap_tile(tile, 0, -1, false);
2624 redraw=true;
2625 }
2626 break;
2627
2628 case KEY_RIGHT:
2629 if(CHECK_CTRL_CMD)
2630 {
2631 unfloat_selection();
2632 tile=zc_min(tile+1, NEWMAXTILES-1);
2633 undocount = tilesize(newtilebuf[tile].format);
2634
2635 for(int32_t i=0; i<undocount; i++)
2636 {
2637 undotile[i]=newtilebuf[tile].data[i];
2638 oldtile[i]=undotile[i];
2639 }
2640
2641 redraw=true;
2642 }
2643 else
2644 {
2645 for(int32_t i=0; i<undocount; i++)
2646 {
2647 undotile[i]=newtilebuf[tile].data[i];
2648 }
2649 for(auto x = 0; x < 16; ++x)
2650 for(auto y = 0; y < 16; ++y)
2651 undoselgrid[x][y] = selection_grid[x+1][y+1];
2652 for(auto q = 0; q < 256; ++q)
2653 undofloatsel[q] = floatsel[q];
2654 undo_is_floatsel = floating_sel;
2655 if(has_selection())
2656 {
2657 float_selection(tile,key[KEY_LSHIFT]||key[KEY_RSHIFT]);
2658 wrap_sel_tile(0, 1);
2659 shift_selection_grid(1, 0);
2660 }
2661 else wrap_tile(tile, 0, 1, false);
2662 redraw=true;
2663 }
2664 break;
2665 case KEY_0: case KEY_1: case KEY_2: case KEY_3:
2666 case KEY_4: case KEY_5: case KEY_6: case KEY_7:
2667 case KEY_8: case KEY_9:
2668 case KEY_0_PAD: case KEY_1_PAD: case KEY_2_PAD: case KEY_3_PAD:
2669 case KEY_4_PAD: case KEY_5_PAD: case KEY_6_PAD: case KEY_7_PAD:
2670 case KEY_8_PAD: case KEY_9_PAD:
2671 {
2672 int t = k - ((k>KEY_9) ? KEY_1_PAD : KEY_1);
2673 if(unsigned(t) < t_max)
2674 {
2675 if(old_tool != -1)
2676 old_tool = t;
2677 else tool = t;
2678 }
2679 break;
2680 }
2681 case KEY_TAB:
2682 {
2683 if(key_shifts & KB_CTRL_FLAG)
2684 {
2685 xmode = (xmode+1)%XMODE_MAX;
2686 if(!xmode)
2687 bgmode = (bgmode+1)%BGMODE_MAX;
2688 }
2689 else if(key_shifts & KB_SHIFT_FLAG)
2690 hide_grid = !hide_grid;
2691 else show_quartgrid = !show_quartgrid;
2692 redraw = true;
2693 break;
2694 }
2695 }
2696 clear_keybuf();
2697 }
2698
2699 if(!gui_mouse_b())
2700 {
2701 if(is_selecting())
2702 {
2703 unfloat_selection();
2704 int32_t x1=zc_min(selecting_x1,selecting_x2);
2705 int32_t x2=zc_max(selecting_x1,selecting_x2);
2706 int32_t y1=zc_min(selecting_y1,selecting_y2);
2707 int32_t y2=zc_max(selecting_y1,selecting_y2);
2708
2709 if(select_mode==0)
2710 {
2711 clear_selection_grid();
2712 }
2713
2714 for(int32_t x=x1; x<=x2; ++x)
2715 {
2716 for(int32_t y=y1; y<=y2; ++y)
2717 {
2718 selection_grid[x+1][y+1]=((select_mode<2)?(1):(((select_mode==2)?(0):(selection_grid[x+1][y+1]))));
2719 }
2720 }
2721
2722 if(select_mode==3)
2723 {
2724 for(int32_t y=0; y<16; ++y)
2725 {
2726 for(int32_t x=0; x<x1; ++x)
2727 {
2728 selection_grid[x+1][y+1]=0;
2729 }
2730
2731 for(int32_t x=x2+1; x<16; ++x)
2732 {
2733 selection_grid[x+1][y+1]=0;
2734 }
2735 }
2736
2737 for(int32_t x=x1; x<=x2; ++x)
2738 {
2739 for(int32_t y=0; y<y1; ++y)
2740 {
2741 selection_grid[x+1][y+1]=0;
2742 }
2743
2744 for(int32_t y=y2+1; y<16; ++y)
2745 {
2746 selection_grid[x+1][y+1]=0;
2747 }
2748 }
2749 }
2750 }
2751
2752 selecting_x1=selecting_x2=selecting_y1=selecting_y2=-1;
2753 did_wand_select=false;
2754 }
2755
2756 bool alt=(key[KEY_ALT]||key[KEY_ALTGR]);
2757 bool shift=(key[KEY_LSHIFT] || key[KEY_RSHIFT]);
2758 bool ctrl=CHECK_CTRL_CMD;
2759 static int32_t last_tool_val = 0;
2760
2761 if(tool==t_select||tool==t_wand)
2762 {
2763 if(!drawing)
2764 {
2765 int32_t type=0;
2766
2767 if(has_selection())
2768 {
2769 if(shift)
2770 {
2771 type+=1;
2772 }
2773
2774 if(alt)
2775 {
2776 type+=2;
2777 }
2778 }
2779
2780 if(type!=select_mode)
2781 {
2782 select_mode=type;
2783
2784 if(isinRect(temp_mouse_x,temp_mouse_y-(tool==t_fill ? (14) : 0),zoomtile.x,zoomtile.y,zoomtile.x+(zoomtile.w*zoomtile.xscale)-2,zoomtile.y+(zoomtile.h*zoomtile.yscale)-2-(tool==t_fill ? (14) : 0))) //inside the zoomed tile window
2785 set_tool_sprite(tool,type);
2786 }
2787 }
2788 }
2789 else if(alt||ctrl)
2790 {
2791 if(old_tool==-1)
2792 {
2793 old_tool = tool;
2794 tool_cur = -1;
2795 }
2796 if(alt&&ctrl)
2797 tool = t_recolor;
2798 else if(alt)
2799 tool = t_eyedropper;
2800 else tool = t_fill;
2801 }
2802 else if(old_tool!=-1)
2803 {
2804 tool = old_tool;
2805 old_tool = -1;
2806 tool_cur = -1;
2807 redraw = true;
2808 }
2809 if(last_tool_val != tool)
2810 {
2811 redraw = true;
2812 tool_cur = -1;
2813 update_tool_cursor();
2814 last_tool_val = tool;
2815 }
2816
2817 if(!bdown)
2818 {
2819 move_origin_x=prev_x=(temp_mouse_x-zoomtile.x)/zoomtile.xscale;
2820 move_origin_y=prev_y=(temp_mouse_y-zoomtile.y)/zoomtile.yscale;
2821 }
2822
2823 if(gui_mouse_b()==1 && !bdown) //pressed the left mouse button
2824 {
2825 if(isinRect(temp_mouse_x,temp_mouse_y,zoomtile.x,zoomtile.y-(tool==t_fill ? (14) : 0),zoomtile.x+(zoomtile.w*zoomtile.xscale)-2,zoomtile.y+(zoomtile.h*zoomtile.yscale)-2-(tool==t_fill ? (14) : 0))) //inside the zoomed tile window
2826 {
2827 if(tool==t_move || tool==t_fill)
2828 {
2829 set_tool_sprite(tool,1);
2830
2831 move_origin_x=prev_x=(temp_mouse_x-zoomtile.x)/zoomtile.xscale;
2832 move_origin_y=prev_y=(temp_mouse_y-zoomtile.y)/zoomtile.yscale;
2833 }
2834
2835 for(int32_t i=0; i<undocount; i++)
2836 {
2837 undotile[i]=newtilebuf[tile].data[i];
2838 }
2839 for(auto x = 0; x < 16; ++x)
2840 for(auto y = 0; y < 16; ++y)
2841 undoselgrid[x][y] = selection_grid[x+1][y+1];
2842 for(auto q = 0; q < 256; ++q)
2843 undofloatsel[q] = floatsel[q];
2844 undo_is_floatsel = floating_sel;
2845
2846 drawing=1;
2847 }
2848
2849 if(ok_button.rect(temp_mouse_x,temp_mouse_y))
2850 {
2851 if(do_text_button(ok_button.x,ok_button.y,ok_button.w,ok_button.h,"OK"))
2852 {
2853 done=2;
2854 }
2855 }
2856
2857 if(cancel_button.rect(temp_mouse_x,temp_mouse_y))
2858 {
2859 if(do_text_button(cancel_button.x,cancel_button.y,cancel_button.w,cancel_button.h,"Cancel"))
2860 {
2861 done=1;
2862 }
2863 }
2864
2865 if(edit_button.rect(temp_mouse_x,temp_mouse_y))
2866 {
2867 if(do_text_button(edit_button.x,edit_button.y,edit_button.w,edit_button.h,"Edit Pal"))
2868 {
2869 colors_menu.pop(edit_button.x+2,edit_button.y-40);
2870 get_palette(tpal);
2871
2872 if(newtilebuf[tile].format==tf4Bit)
2873 {
2874 invcol=makecol8(255 - tpal[CSET(cs)].r, 255 - tpal[CSET(cs)].g, 255 - tpal[CSET(cs)].b);
2875 }
2876 else
2877 {
2878 invcol=makecol8(255 - tpal[0].r, 255 - tpal[0].g, 255 - tpal[0].b);
2879 }
2880
2881 redraw=true;
2882 }
2883 }
2884
2885 int sqr_clicked;
2886 if(show_quartgrid && qgrid_tool(tool))
2887 {
2888 sqr_clicked = reflbtn_grid.rectind(temp_mouse_x,temp_mouse_y);
2889 if(sqr_clicked > -1)
2890 {
2891 auto& sqr = reflbtn_grid.subsquare(sqr_clicked);
2892 if(do_text_button(sqr.x,sqr.y,sqr.w,sqr.h,reflbtn_names[sqr_clicked]))
2893 refl_flags ^= (1<<sqr_clicked);
2894 }
2895 }
2896 sqr_clicked = xmodebtn_grid.rectind(temp_mouse_x,temp_mouse_y);
2897 if(sqr_clicked > -1)
2898 {
2899 auto& sqr = xmodebtn_grid.subsquare(sqr_clicked);
2900 if(do_text_button(sqr.x,sqr.y,sqr.w,sqr.h,xmodebtn_names[sqr_clicked]))
2901 xmode = sqr_clicked;
2902 }
2903 sqr_clicked = bgmodebtn_grid.rectind(temp_mouse_x,temp_mouse_y);
2904 if(sqr_clicked > -1)
2905 {
2906 auto& sqr = bgmodebtn_grid.subsquare(sqr_clicked);
2907 if(do_text_button(sqr.x,sqr.y,sqr.w,sqr.h,bgmodebtn_names[sqr_clicked]))
2908 bgmode = sqr_clicked;
2909 }
2910
2911 if(showcolortip)
2912 {
2913 if(color_info.rect(temp_mouse_x,temp_mouse_y))
2914 {
2915 showcolortip = 0;
2916 zc_set_config("ZQ_GUI","tile_edit_colornames",0);
2917 }
2918 }
2919 else
2920 {
2921 if(color_info_btn.rect(temp_mouse_x,temp_mouse_y))
2922 {
2923 if(do_text_button(color_info_btn.x,color_info_btn.y,color_info_btn.w,color_info_btn.h,"Show Colors"))
2924 {
2925 showcolortip = 1;
2926 zc_set_config("ZQ_GUI","tile_edit_colornames",1);
2927 redraw=true;
2928 }
2929 }
2930 }
2931
2932 if(hlcbox.rect(temp_mouse_x,temp_mouse_y))
2933 {
2934 if(do_checkbox(screen2,hlcbox.x,hlcbox.y,hlcbox.w,hlcbox.h,tthighlight))
2935 {
2936 zc_set_config("ZQ_GUI","tile_edit_fancyhighlight",tthighlight);
2937 redraw=true;
2938 }
2939 }
2940 if(quartgrid_cbox.rect(temp_mouse_x,temp_mouse_y))
2941 {
2942 if(do_checkbox(screen2,quartgrid_cbox.x,quartgrid_cbox.y,quartgrid_cbox.w,quartgrid_cbox.h,show_quartgrid))
2943 redraw=true;
2944 }
2945 if(hidegrid_cbox.rect(temp_mouse_x,temp_mouse_y))
2946 {
2947 if(do_checkbox(screen2,hidegrid_cbox.x,hidegrid_cbox.y,hidegrid_cbox.w,hidegrid_cbox.h,hide_grid))
2948 redraw=true;
2949 }
2950
2951 switch(newtilebuf[tile].format)
2952 {
2953 case tf4Bit:
2954 {
2955 auto ind = cpalette_4.rectind(temp_mouse_x,temp_mouse_y);
2956 if(ind > -1)
2957 {
2958 c1 = ind;
2959 redraw=true;
2960 }
2961 break;
2962 }
2963 case tf8Bit:
2964 {
2965 auto ind = cpalette_8.rectind(temp_mouse_x,temp_mouse_y);
2966 if(ind > -1)
2967 {
2968 c1 = ind;
2969 redraw=true;
2970 }
2971 break;
2972 }
2973 }
2974
2975
2976 int32_t newtool = tool_btns.rectind(temp_mouse_x,temp_mouse_y);
2977 if(newtool > -1 && newtool < t_max)
2978 {
2979 tool=newtool;
2980 redraw=true;
2981 }
2982
2983 if(x_btn.rect(temp_mouse_x,temp_mouse_y))
2984 {
2985 if(do_x_button(screen, x_btn.x, x_btn.y))
2986 {
2987 done=1;
2988 }
2989 }
2990 if(info_btn.rect(temp_mouse_x,temp_mouse_y))
2991 {
2992 if(do_question_button(screen, info_btn.x, info_btn.y))
2993 {
2994 show_edit_tile_help();
2995 }
2996 }
2997
2998 bdown=true;
2999 }
3000
3001 if(gui_mouse_b()&2 && !bdown) //pressed the right mouse button
3002 {
3003 if(isinRect(temp_mouse_x,temp_mouse_y,zoomtile.x,zoomtile.y-(tool==t_fill ? (14) : 0),zoomtile.x+(zoomtile.w*zoomtile.xscale)-2,zoomtile.y+(zoomtile.h*zoomtile.yscale)-2-(tool==t_fill ? (14) : 0))) //inside the zoomed tile window
3004 {
3005 if(tool==t_move || tool==t_fill)
3006 {
3007 set_tool_sprite(tool,1);
3008
3009 move_origin_x=prev_x=(temp_mouse_x-zoomtile.x)/zoomtile.xscale;
3010 move_origin_y=prev_y=(temp_mouse_y-zoomtile.y)/zoomtile.yscale;
3011 }
3012
3013 for(int32_t i=0; i<undocount; i++)
3014 {
3015 undotile[i]=newtilebuf[tile].data[i];
3016 }
3017 for(auto x = 0; x < 16; ++x)
3018 for(auto y = 0; y < 16; ++y)
3019 undoselgrid[x][y] = selection_grid[x+1][y+1];
3020 for(auto q = 0; q < 256; ++q)
3021 undofloatsel[q] = floatsel[q];
3022 undo_is_floatsel = floating_sel;
3023
3024 drawing=2;
3025 }
3026
3027 switch(newtilebuf[tile].format)
3028 {
3029 case tf4Bit:
3030 {
3031 auto ind = cpalette_4.rectind(temp_mouse_x,temp_mouse_y);
3032 if(ind > -1)
3033 {
3034 c2 = ind;
3035 redraw=true;
3036 }
3037 break;
3038 }
3039 case tf8Bit:
3040 {
3041 auto ind = cpalette_8.rectind(temp_mouse_x,temp_mouse_y);
3042 if(ind > -1)
3043 {
3044 c2 = ind;
3045 redraw=true;
3046 }
3047 break;
3048 }
3049 }
3050
3051 bdown=true;
3052 }
3053
3054 if(bdown&&!gui_mouse_b()) //released the buttons
3055 {
3056 if(isinRect(temp_mouse_x,temp_mouse_y,zoomtile.x,zoomtile.y-(tool==t_fill ? (14) : 0),zoomtile.x+(zoomtile.w*zoomtile.xscale)-2,zoomtile.y+(zoomtile.h*zoomtile.yscale)-2-(tool==t_fill ? (14) : 0))) //inside the zoomed tile window
3057 {
3058 if(tool==t_move || tool==t_fill)
3059 {
3060 set_tool_sprite(tool,0);
3061 }
3062 }
3063 }
3064
3065 if(drawing && zoomtile.rect(temp_mouse_x,temp_mouse_y)) //inside the zoomed tile window
3066 {
3067 int32_t ind = zoomtile.rectind(temp_mouse_x,temp_mouse_y);
3068 int32_t x=ind%zoomtile.w;
3069 int32_t y=ind/zoomtile.w;
3070
3071 bool reset_draw = false;
3072
3073 if(__pixel_draw(x,y,tile,flip))
3074 reset_draw = true;
3075 if(show_quartgrid)
3076 {
3077 auto tmp_sel_mode = select_mode;
3078 if(tool == t_wand && select_mode == 0)
3079 select_mode = 1;
3080 if(qgrid_tool(tool))
3081 {
3082 if(refl_flags & (1<<REFL_HFLIP))
3083 if(__pixel_draw(15-x,y,tile,flip))
3084 reset_draw = true;
3085 if(refl_flags & (1<<REFL_VFLIP))
3086 if(__pixel_draw(x,15-y,tile,flip))
3087 reset_draw = true;
3088 //Diagonal flip and 180° rotation are the same!
3089 if(refl_flags & ((1<<REFL_DBLFLIP)|(1<<REFL_180)))
3090 if(__pixel_draw(15-x,15-y,tile,flip))
3091 reset_draw = true;
3092 if(refl_flags & (1<<REFL_90CW))
3093 if(__pixel_draw(15-y,x,tile,flip))
3094 reset_draw = true;
3095 if(refl_flags & (1<<REFL_90CCW))
3096 if(__pixel_draw(y,15-x,tile,flip))
3097 reset_draw = true;
3098 }
3099 select_mode = tmp_sel_mode;
3100 }
3101
3102 if(reset_draw)
3103 drawing = 0;
3104 redraw=true;
3105 }
3106
3107 if(gui_mouse_b()==0)
3108 {
3109 bdown=false;
3110 drawing=0;
3111 }
3112
3113 temp_x=(gui_mouse_x()-zoomtile.x)/zoomtile.xscale;
3114 temp_y=(gui_mouse_y()-zoomtile.y)/zoomtile.yscale;
3115
3116 {
3117 tile_x=temp_x;
3118 tile_y=temp_y;
3119 redraw=true;
3120 }
3121
3122 const char *toolnames[t_max]=
3123 {
3124 "Pen\nDraw Single Pixels", "Fill\nCtrl", "Replace Color\nCtrl+Alt", "Grab Color\nAlt", "Move\nMove Selections", "Select Pixels", "Select Color"
3125 };
3126
3127 int32_t toolbtn = tool_btns.rectind(temp_mouse_x,temp_mouse_y);
3128 if(toolbtn > -1 && toolbtn < t_max)
3129 {
3130 int32_t column = toolbtn%tool_btns.w;
3131 int32_t row = toolbtn/tool_btns.w;
3132
3133 update_tooltip(temp_mouse_x,temp_mouse_y,tool_btns.x+(column*tool_btns.xscale),tool_btns.y+(row*tool_btns.yscale),tool_btns.xscale,tool_btns.yscale, toolnames[toolbtn]);
3134 redraw=true;
3135 }
3136 /* Highlight the hovered pixel? Eh, maybe too much?
3137 int32_t hov_pix = zoomtile.rectind(temp_mouse_x,temp_mouse_y);
3138 if(hov_pix > -1)
3139 {
3140 int32_t column = hov_pix%zoomtile.w;
3141 int32_t row = hov_pix/zoomtile.w;
3142
3143 update_tooltip(temp_mouse_x,temp_mouse_y,zoomtile.x+(column*zoomtile.xscale),zoomtile.y+(row*zoomtile.yscale),zoomtile.xscale,zoomtile.yscale, NULL);
3144 redraw=true;
3145 }*/
3146
3147 if(redraw)
3148 {
3149 custom_vsync();
3150 draw_edit_scr(tile,flip,cs,oldtile, false);
3151 }
3152 else
3153 {
3154 bool hs=has_selection();
3155
3156 if(hs)
3157 {
3158 zoomtile16(screen2,tile,zoomtile.x-1,zoomtile.y-1,cs,flip,zoomtile.xscale);
3159 }
3160
3161 custom_vsync();
3162
3163 if(hs)
3164 {
3165 // blit(screen2, screen, 79, 31, 79, 31, 129, 129);
3166 blit(screen2, screen, zoomtile.x-1,zoomtile.y-1, zoomtile.x-1,zoomtile.y-1, (zoomtile.w*zoomtile.xscale)+1, (zoomtile.h*zoomtile.yscale)+1);
3167 }
3168
3169 update_tool_cursor();
3170 SCRFIX();
3171 }
3172
3173 }
3174 while(!done);
3175
3176 unfloat_selection();
3177 clear_selection_grid();
3178
3179 while(gui_mouse_b())
3180 {
3181 /* do nothing */
3182 rest(1);
3183 }
3184
3185 if(done==1)
3186 {
3187 for(int32_t i=0; i<undocount; i++)
3188 {
3189 newtilebuf[tile].data[i]=oldtile[i];
3190 }
3191 }
3192 else
3193 {
3194 byte *buf = new byte[undocount];
3195
3196 // put back old tile
3197 for(int32_t i=0; i<undocount; i++)
3198 {
3199 buf[i] = newtilebuf[tile].data[i];
3200 newtilebuf[tile].data[i] = oldtile[i];
3201 }
3202
3203 // go
3204 go_tiles();
3205
3206 // replace old tile with new one again
3207 for(int32_t i=0; i<undocount; i++)
3208 {
3209 newtilebuf[tile].data[i] = buf[i];
3210 }
3211
3212 // usetiles=true;
3213 saved=false;
3214
3215 if(buf!=NULL)
3216 {
3217 delete[] buf;
3218 }
3219 }
3220
3221 MouseSprite::set(ZQM_NORMAL);
3222 register_blank_tiles();
3223 register_used_tiles();
3224 clear_tooltip();
3225 comeback();
3226 destroy_bitmap(selection_pattern);
3227 destroy_bitmap(selecting_pattern);
3228 destroy_bitmap(intersection_pattern);
3229 font = oldfont;
3230 popup_zqdialog_end();
3231 }
3232
3233 /* Grab Tile Code */
3234
3235 enum recolorState { rcNone, rc4Bit, rc8Bit };
3236
3237 BITMAP* original_imagebuf_bitmap=NULL;
3238 void *imagebuf=NULL;
3239 int32_t imagebuf_bitmap_scale=0;
3240 #define IMAGEBUF_SCALE (imagebuf_bitmap_scale > 0 ? imagebuf_bitmap_scale : 1.0 / -imagebuf_bitmap_scale)
3241 int32_t imagesize=0;
3242 int32_t tilecount=0;
3243 int32_t imagetype=0;
3244 int32_t imagex,imagey,selx,sely;
3245 int32_t bp=4,grabmode=16,romofs=0,romtilemode=0, romtilecols=8;
3246 bool nesmode=false;
3247 int32_t grabmask=0;
3248 recolorState recolor=rcNone;
3249 PALETTE imagepal;
3250
3251 /* bestfit_color:
3252 * Searches a palette for the color closest to the requested R, G, B value.
3253 */
3254 int32_t bestfit_cset_color(int32_t cs, int32_t r, int32_t g, int32_t b)
3255 {
3256 int32_t bestMatch = 0; // Color with the lowest total difference so far
3257 float bestTotalDiff = 100000; // Total difference between requested color and bestMatch
3258 float bestHighDiff = 100000; // Greatest difference of R, G, B between requested color and bestMatch
3259
3260 for(int32_t i = 0; i < CSET_SIZE; i++)
3261 {
3262 byte *rgbByte;
3263
3264 // This seems to be right...
3265 if(cs==2 || cs==3 || cs==4)
3266 rgbByte = colordata + (CSET((Map.CurrScr()->color) * pdLEVEL + (cs-2) + pdFULL) + i) * 3;
3267 else if(cs==9)
3268 rgbByte = colordata + (CSET((Map.CurrScr()->color) * pdLEVEL + 3 + pdFULL) + i) * 3;
3269 else if(cs==1&&get_qr(qr_CSET1_LEVEL))
3270 rgbByte = colordata + (CSET((Map.CurrScr()->color) * pdLEVEL + poNEWCSETS) + i) * 3;
3271 else if(cs==5&&get_qr(qr_CSET5_LEVEL))
3272 rgbByte = colordata + (CSET((Map.CurrScr()->color) * pdLEVEL + poNEWCSETS + 1) + i) * 3;
3273 else if(cs==7&&get_qr(qr_CSET7_LEVEL))
3274 rgbByte = colordata + (CSET((Map.CurrScr()->color) * pdLEVEL + poNEWCSETS + 2) + i) * 3;
3275 else if(cs==8&&get_qr(qr_CSET8_LEVEL))
3276 rgbByte = colordata + (CSET((Map.CurrScr()->color) * pdLEVEL + poNEWCSETS + 3) + i) * 3;
3277 else
3278 rgbByte = colordata + (CSET(cs)+i)*3;
3279
3280 int32_t dr=r-*rgbByte;
3281 int32_t dg=g-*(rgbByte+1);
3282 int32_t db=b-*(rgbByte+2);
3283
3284 // Track both the total color difference and the single greatest
3285 // difference of R, G, B. The idea is that it's better to have
3286 // two or three small differences than one big one.
3287 // The differences are multiplied by different numbers to account
3288 // for the differences in perceived brightness of the three colors.
3289 float totalDiff = sqrt(dr*dr*0.241 + dg*dg*0.691 + db*db*0.068);
3290 float highDiff = zc_max(zc_max(sqrt(dr*dr*0.241), sqrt(dg*dg*0.691)), sqrt(db*db*0.068));
3291
3292 // Perfect match? Just stop here.
3293 if(totalDiff==0)
3294 return i;
3295
3296 if(totalDiff < bestTotalDiff || // Best match so far?
3297 (totalDiff == bestTotalDiff && highDiff < bestHighDiff)) // Equally good match with lower high difference?
3298 {
3299 bestMatch=i;
3300 bestTotalDiff=totalDiff;
3301 bestHighDiff=highDiff;
3302 }
3303 }
3304
3305 return bestMatch;
3306 }
3307
3308 // Same as the above, but draws from all colors in CSets 0-11.
3309 int32_t bestfit_cset_color_8bit(int32_t r, int32_t g, int32_t b)
3310 {
3311 int32_t bestMatch = 0;
3312 float bestTotalDiff = 100000;
3313 float bestHighDiff = 100000;
3314
3315 for(int32_t i = 0; i < 192; i++) // 192 colors in CSets 0-11
3316 {
3317 byte *rgbByte;
3318
3319 int32_t cs=i>>4;
3320 if(cs==2 || cs==3 || cs==4)
3321 rgbByte = colordata + (CSET((Map.CurrScr()->color) * pdLEVEL + (cs-2) + pdFULL) + (i%16)) * 3;
3322 else if(cs==9)
3323 rgbByte = colordata + (CSET((Map.CurrScr()->color) * pdLEVEL + 3 + pdFULL) + (i%16)) * 3;
3324 else if(cs==1&&get_qr(qr_CSET1_LEVEL))
3325 rgbByte = colordata + (CSET((Map.CurrScr()->color) * pdLEVEL + poNEWCSETS) + (i%16)) * 3;
3326 else if(cs==5&&get_qr(qr_CSET5_LEVEL))
3327 rgbByte = colordata + (CSET((Map.CurrScr()->color) * pdLEVEL + poNEWCSETS + 1) + (i%16)) * 3;
3328 else if(cs==7&&get_qr(qr_CSET7_LEVEL))
3329 rgbByte = colordata + (CSET((Map.CurrScr()->color) * pdLEVEL + poNEWCSETS + 2) + (i%16)) * 3;
3330 else if(cs==8&&get_qr(qr_CSET8_LEVEL))
3331 rgbByte = colordata + (CSET((Map.CurrScr()->color) * pdLEVEL + poNEWCSETS + 3) + (i%16)) * 3;
3332 else
3333 rgbByte = colordata + i * 3;
3334
3335 int32_t dr=r-*rgbByte;
3336 int32_t dg=g-*(rgbByte+1);
3337 int32_t db=b-*(rgbByte+2);
3338
3339 float totalDiff = sqrt(dr*dr*0.241 + dg*dg*0.691 + db*db*0.068);
3340 float highDiff = zc_max(zc_max(sqrt(dr*dr*0.241), sqrt(dg*dg*0.691)), sqrt(db*db*0.068));
3341
3342 if(totalDiff==0) // Perfect match?
3343 return i;
3344
3345 if(totalDiff < bestTotalDiff || // Best match so far?
3346 (totalDiff == bestTotalDiff && highDiff < bestHighDiff)) // Equally good match with lower high difference?
3347 {
3348 bestMatch=i;
3349 bestTotalDiff=totalDiff;
3350 bestHighDiff=highDiff;
3351 }
3352 }
3353
3354 return bestMatch;
3355 }
3356
3357 byte cset_reduce_table[PAL_SIZE];
3358
3359 void calc_cset_reduce_table(PALETTE pal, int32_t cs)
3360 {
3361 for(int32_t i=0; i<PAL_SIZE; i++)
3362 {
3363 cset_reduce_table[i]=(bestfit_cset_color(cs, pal[i].r, pal[i].g, pal[i].b)&0x0F);
3364 }
3365 }
3366
3367 void calc_cset_reduce_table_8bit(PALETTE pal)
3368 {
3369 for(int32_t i=0; i<PAL_SIZE; i++)
3370 {
3371 cset_reduce_table[i]=bestfit_cset_color_8bit(pal[i].r, pal[i].g, pal[i].b);
3372 }
3373 }
3374
3375 void puttileROM(BITMAP *dest,int32_t x,int32_t y,byte *src,int32_t cs)
3376 {
3377 //storage space for the grabbed image
3378 byte buf[64];
3379 memset(buf,0,64);
3380 byte *oldsrc=src;
3381
3382 //for 8 lines in the source image...
3383 for(int32_t line=0; line<(nesmode?4:8); line++)
3384 {
3385 //bx is the pixel at the start of a line in the storage buffer
3386 int32_t bx=line<<(nesmode?4:3);
3387 //b is a byte in the source image (either an entire line in 1bp or the start of a line in others)
3388 byte b=src[(bp&1)?line:line<<1];
3389
3390 //fill the storage buffer with data from the source image
3391 for(int32_t i=7; i>=0; --i)
3392 {
3393 buf[bx+i] = (b&1)+(cs<<4);
3394 b>>=1;
3395 }
3396 }
3397
3398 ++src;
3399
3400 for(int32_t p=1; p<bp; p++)
3401 {
3402 for(int32_t line=0; line<(nesmode?4:8); line++)
3403 {
3404 int32_t bx=line<<(nesmode?4:3);
3405 byte b=src[(bp&1)?line:line<<1];
3406
3407 for(int32_t i=7; i>=0; --i)
3408 {
3409 if(nesmode)
3410 {
3411 buf[bx+8+i] = (b&1)+(cs<<4);
3412 }
3413 else
3414 {
3415 buf[bx+i] |= (b&1)<<p;
3416 }
3417
3418 b>>=1;
3419 }
3420 }
3421
3422 if(p&1)
3423 {
3424 src+=15;
3425 }
3426 else
3427 {
3428 ++src;
3429 }
3430 }
3431
3432
3433 if(nesmode)
3434 {
3435 src=oldsrc;
3436
3437 for(int32_t counter=0; counter<2; ++counter, ++src)
3438 {
3439 //for 8 lines in the source image...
3440 for(int32_t line=0; line<4; line++)
3441 {
3442 //bx is the pixel at the start of a line in the storage buffer
3443 int32_t bx=line<<4;
3444 //b is a byte in the source image (either an entire line in 1bp or the start of a line in others)
3445 byte b=src[(line+4)<<1];
3446
3447 //fill the storage buffer with data from the source image
3448 for(int32_t i=7; i>=0; --i)
3449 {
3450 // buf[bx+i] = (b&1)+(cs<<4);
3451 buf[bx+(counter<<3)+i] |= (b&1)<<1;
3452 b>>=1;
3453 }
3454 }
3455 }
3456 }
3457
3458 int32_t c=0;
3459
3460 switch(romtilemode)
3461 {
3462 case 0:
3463 case 1:
3464 case 2:
3465 for(int32_t j=0; j<8; j++)
3466 {
3467 for(int32_t i=0; i<8; i++)
3468 {
3469 putpixel(dest,x+i,y+j,buf[c++]);
3470 }
3471 }
3472
3473 break;
3474
3475 case 3:
3476 for(int32_t j=0; j<4; j++)
3477 {
3478 for(int32_t i=0; i<16; i++)
3479 {
3480 putpixel(dest,x+i,y+j,buf[c++]);
3481 }
3482 }
3483
3484 break;
3485 }
3486 }
3487
3488 const char *file_type[ftMAX]=
3489 {
3490 "None", "BIN", "BMP", "TIL", "ZGP", "QSU", "ZQT", "QST"
3491 };
3492
3493 void draw_grab_window()
3494 {
3495 int w = 640;
3496 int h = 480;
3497 int window_xofs=0;//(zq_screen_w-w-12)>>1;
3498 int window_yofs=0;//(zq_screen_h-h-25-6)>>1;
3499 jwin_draw_win(screen, window_xofs, window_yofs, w+6+6, h+25+6, FR_WIN);
3500 jwin_draw_frame(screen, window_xofs+4, window_yofs+23, w+2+2, h+2+2-(79*2), FR_DEEP);
3501
3502 FONT *oldfont = font;
3503 font = get_zc_font(font_lfont);
3504 jwin_draw_titlebar(screen, window_xofs+3, window_yofs+3, w+6, 18, "Grab Tile(s)", true);
3505 font=oldfont;
3506 }
3507
3508 void draw_grab_scr(int32_t tile,int32_t cs,byte *newtile,int32_t black,int32_t white, int32_t width, int32_t height, byte *newformat)
3509 {
3510 width=width;
3511 height=height;
3512 white=white; // happy birthday compiler
3513
3514 int32_t yofs=0;
3515 //clear_to_color(screen2,bg);
3516 rectfill(screen2, 0, 0, 319, 159, black);
3517 rectfill(screen2,0,162,319,239,jwin_pal[jcBOX]);
3518 hline(screen2, 0, 160, 319, jwin_pal[jcMEDLT]);
3519 hline(screen2, 0, 161, 319, jwin_pal[jcLIGHT]);
3520 yofs=3;
3521
3522 // text_mode(-1);
3523 int32_t tileromcolumns=20;
3524
3525 switch(imagetype)
3526 {
3527 case ftBMP:
3528 if(recolor==rcNone)
3529 {
3530 blit((BITMAP*)imagebuf,screen2,imagex<<4,imagey<<4,0,0,320,160);
3531 }
3532 else
3533 {
3534 int32_t maxy=zc_min(160,((BITMAP*)imagebuf)->h);
3535 int32_t maxx=zc_min(320,((BITMAP*)imagebuf)->w);
3536
3537 for(int32_t y=0; y<maxy; y++)
3538 {
3539 if((imagey<<4)+y>=((BITMAP*)imagebuf)->h)
3540 {
3541 break;
3542 }
3543
3544 for(int32_t x=0; x<maxx; x++)
3545 {
3546 if((imagex<<4)+x>=((BITMAP*)imagebuf)->w)
3547 {
3548 break;
3549 }
3550
3551 if(recolor==rc8Bit)
3552 screen2->line[y][x]=cset_reduce_table[((BITMAP*)imagebuf)->line[(imagey<<4)+y][(imagex<<4)+x]];
3553 else
3554 screen2->line[y][x]=(cset_reduce_table[((BITMAP*)imagebuf)->line[(imagey<<4)+y][(imagex<<4)+x]])+(cs<<4);
3555 }
3556 }
3557 }
3558
3559 break;
3560
3561 case ftZGP:
3562 case ftQST:
3563 case ftZQT:
3564 case ftQSU:
3565 case ftTIL:
3566 {
3567 tiledata *hold = newtilebuf;
3568 newtilebuf = grabtilebuf;
3569 //fixme
3570 imagey = vbound(imagey, 0, MAXTILEROWS); //fixed -Z This can no longer crash if you scroll past the end of the tile pages. 6th June, 2020
3571 int32_t t=imagey*TILES_PER_ROW;
3572
3573 for(int32_t i=0; i<200; i++) // 10 rows, down to y=160
3574 {
3575 if(t <= tilecount)
3576 {
3577 puttile16(screen2,t,(i%TILES_PER_ROW)<<4,(i/TILES_PER_ROW)<<4,cs,0);
3578 }
3579
3580 ++t;
3581 }
3582
3583 newtilebuf = hold;
3584 //fixme
3585 }
3586 break;
3587
3588 case ftBIN:
3589 {
3590 int32_t ofs = (tileromcolumns*imagex + imagey) * 128*bp + romofs;
3591 byte *buf = (byte*)imagebuf;
3592
3593 switch(romtilemode)
3594 {
3595 case 0:
3596 for(int32_t y=0; y<160; y+=8)
3597 {
3598 for(int32_t x=0; ((x<128)&&(ofs<=imagesize-8*bp)); x+=8)
3599 {
3600 puttileROM(screen2,x,y,buf+ofs,cs);
3601 ofs+=8*bp;
3602 }
3603 }
3604
3605 for(int32_t y=0; y<160; y+=8)
3606 {
3607 for(int32_t x=0; ((x<128)&&(ofs<=imagesize-8*bp)); x+=8)
3608 {
3609 puttileROM(screen2,x+128,y,buf+ofs,cs);
3610 ofs+=8*bp;
3611 }
3612 }
3613
3614 break;
3615
3616 case 1:
3617 for(int32_t y=0; y<160; y+=16)
3618 {
3619 for(int32_t x=0; ((x<128)&&(ofs<=imagesize-8*bp)); x+=8)
3620 {
3621 puttileROM(screen2,x,y,buf+ofs,cs);
3622 ofs+=8*bp;
3623 puttileROM(screen2,x,y+8,buf+ofs,cs);
3624 ofs+=8*bp;
3625 }
3626 }
3627
3628 for(int32_t y=0; y<160; y+=16)
3629 {
3630 for(int32_t x=0; ((x<128)&&(ofs<=imagesize-8*bp)); x+=8)
3631 {
3632 puttileROM(screen2,x+128,y,buf+ofs,cs);
3633 ofs+=8*bp;
3634 puttileROM(screen2,x+128,y+8,buf+ofs,cs);
3635 ofs+=8*bp;
3636 }
3637 }
3638
3639 break;
3640
3641 case 2:
3642 for(int32_t y=0; y<160; y+=16)
3643 {
3644 for(int32_t x=0; ((x<128)&&(ofs<=imagesize-8*bp)); x+=16)
3645 {
3646 puttileROM(screen2,x,y,buf+ofs,cs);
3647 ofs+=8*bp;
3648 puttileROM(screen2,x+8,y,buf+ofs,cs);
3649 ofs+=8*bp;
3650 puttileROM(screen2,x,y+8,buf+ofs,cs);
3651 ofs+=8*bp;
3652 puttileROM(screen2,x+8,y+8,buf+ofs,cs);
3653 ofs+=8*bp;
3654 }
3655 }
3656
3657 for(int32_t y=0; y<160; y+=16)
3658 {
3659 for(int32_t x=0; ((x<128)&&(ofs<=imagesize-8*bp)); x+=16)
3660 {
3661 puttileROM(screen2,x+128,y,buf+ofs,cs);
3662 ofs+=8*bp;
3663 puttileROM(screen2,x+136,y,buf+ofs,cs);
3664 ofs+=8*bp;
3665 puttileROM(screen2,x+128,y+8,buf+ofs,cs);
3666 ofs+=8*bp;
3667 puttileROM(screen2,x+136,y+8,buf+ofs,cs);
3668 ofs+=8*bp;
3669 }
3670 }
3671
3672 break;
3673
3674 case 3:
3675 for(int32_t y=0; y<160; y+=16)
3676 {
3677 for(int32_t x=0; ((x<128)&&(ofs<=imagesize-8*bp)); x+=16)
3678 {
3679 puttileROM(screen2,x,y,buf+ofs,cs);
3680 ofs+=8*bp;
3681 puttileROM(screen2,x,y+4,buf+ofs,cs);
3682 ofs+=8*bp;
3683 puttileROM(screen2,x,y+8,buf+ofs,cs);
3684 ofs+=8*bp;
3685 puttileROM(screen2,x,y+12,buf+ofs,cs);
3686 ofs+=8*bp;
3687 }
3688 }
3689
3690 for(int32_t y=0; y<160; y+=16)
3691 {
3692 for(int32_t x=0; ((x<128)&&(ofs<=imagesize-8*bp)); x+=16)
3693 {
3694 puttileROM(screen2,x+128,y,buf+ofs,cs);
3695 ofs+=8*bp;
3696 puttileROM(screen2,x+128,y+4,buf+ofs,cs);
3697 ofs+=8*bp;
3698 puttileROM(screen2,x+128,y+8,buf+ofs,cs);
3699 ofs+=8*bp;
3700 puttileROM(screen2,x+128,y+12,buf+ofs,cs);
3701 ofs+=8*bp;
3702 }
3703 }
3704
3705 break;
3706 }
3707 }
3708 break;
3709 }
3710
3711 tiledata hold;
3712 bool holdblank = blank_tile_table[0];
3713
3714 if(is_valid_format(newtilebuf[0].format))
3715 {
3716 hold.format = newtilebuf[0].format;
3717 hold.data = (byte *)malloc(tilesize(hold.format));
3718 memcpy(hold.data, newtilebuf[0].data, tilesize(hold.format));
3719 }
3720 else
3721 {
3722 hold.format=tfInvalid;
3723 hold.data=NULL;
3724 }
3725
3726 newtilebuf[0].format=newformat[0];
3727 blank_tile_table[0] = false;
3728
3729 if(newtilebuf[0].data!=NULL)
3730 {
3731 free(newtilebuf[0].data);
3732 }
3733
3734 if(is_valid_format(newtilebuf[0].format))
3735 {
3736 newtilebuf[0].data = (byte *)malloc(tilesize(newtilebuf[0].format));
3737
3738 for(int32_t i=0; i<tilesize(newtilebuf[0].format); i++)
3739 {
3740 newtilebuf[0].data[i]=newtile[i];
3741 }
3742 }
3743 else
3744 {
3745 newtilebuf[0].data=NULL;
3746 }
3747
3748 puttile16(screen2,0,208,168+yofs,cs,0);
3749 overtile16(screen2,0,232,168+yofs,cs,0);
3750 newtilebuf[0].format=hold.format;
3751 blank_tile_table[0] = holdblank;
3752
3753 if(newtilebuf[0].data!=NULL)
3754 {
3755 free(newtilebuf[0].data);
3756 }
3757
3758 if(is_valid_format(newtilebuf[0].format))
3759 {
3760 newtilebuf[0].data = (byte *)malloc(tilesize(newtilebuf[0].format));
3761
3762 for(int32_t i=0; i<256; i++)
3763 {
3764 newtilebuf[0].data[i]=hold.data[i];
3765 }
3766 }
3767 else
3768 {
3769 newtilebuf[0].data=NULL;
3770 }
3771
3772 if(hold.data!=NULL)
3773 {
3774 free(hold.data);
3775 }
3776
3777 puttile16(screen2,tile,208,192+yofs,cs,0);
3778 overtile16(screen2,tile,232,192+yofs,cs,0);
3779
3780 rectfill(screen2,184,168+yofs,191,175+yofs,grabmask&1?vc(12):vc(7));
3781 rectfill(screen2,192,168+yofs,199,175+yofs,grabmask&2?vc(12):vc(7));
3782 rectfill(screen2,184,176+yofs,191,183+yofs,grabmask&4?vc(12):vc(7));
3783 rectfill(screen2,192,176+yofs,199,183+yofs,grabmask&8?vc(12):vc(7));
3784
3785 // rect(screen2,183,167,200,184,dvc(7*2));
3786 // rect(screen2,207,167,224,184,dvc(7*2));
3787 // rect(screen2,231,167,248,184,dvc(7*2));
3788 // rect(screen2,207,191,224,208,dvc(7*2));
3789 // rect(screen2,231,191,248,208,dvc(7*2));
3790
3791 /*
3792 rect(screen2,183,167,200,184,vc(14));
3793 rect(screen2,207,167,224,184,vc(14));
3794 rect(screen2,231,167,248,184,vc(14));
3795 rect(screen2,207,191,224,208,vc(14));
3796 rect(screen2,231,191,248,208,vc(14));
3797 */
3798 jwin_draw_frame(screen2,182,166+yofs,20,20,FR_DEEP);
3799 jwin_draw_frame(screen2,206,166+yofs,20,20,FR_DEEP);
3800 jwin_draw_frame(screen2,230,166+yofs,20,20,FR_DEEP);
3801 jwin_draw_frame(screen2,206,190+yofs,20,20,FR_DEEP);
3802 jwin_draw_frame(screen2,230,190+yofs,20,20,FR_DEEP);
3803 int32_t screen_xofs=6;
3804 int32_t screen_yofs=25;
3805 int winh = 511;
3806 int32_t mul = 2;
3807
3808 yofs=16;
3809
3810 custom_vsync();
3811
3812 stretch_blit(screen2,screen,0,0,320,240,screen_xofs,screen_yofs,640,480);
3813
3814 // Suspend the current font while draw_text_button does its work
3815 FONT* oldfont = font;
3816
3817 font = get_zc_font(font_lfont_l);
3818
3819 int txt_x = 8*mul;
3820 int rbtn_x = 255*mul;
3821 int max_fpath_wid = rbtn_x-2-txt_x;
3822 int max_fpath_wid2 = max_fpath_wid-text_length(font,"... ");
3823 // Interface
3824 switch(imagetype)
3825 {
3826 case 0:
3827 textprintf_ex(screen,font,txt_x,(216+yofs)*mul,jwin_pal[jcTEXTFG],jwin_pal[jcBOX],"%s",imgstr[imagetype]);
3828 break;
3829
3830 case ftBMP:
3831 {
3832 std::string text = fmt::format("{} {}x{}, {:.2g}x zoom with , and .", imgstr[imagetype], original_imagebuf_bitmap->w, original_imagebuf_bitmap->h, IMAGEBUF_SCALE);
3833 int text_x = txt_x;
3834 int text_y = (216 + yofs) * mul;
3835 // TODO: can almost use this, but drawing is offset. prob cuz drawing to a different bitmap than the normal screen bitmap? idk
3836 // int text_w = text_length(font, text.c_str());
3837 // int text_h = text_height(font);
3838 // static int grab_scale_tooltip_id = ttip_register_id();
3839 // ttip_install(grab_scale_tooltip_id, "zoom with , and .", text_x, text_y, text_w, text_h, text_x, text_y - 40);
3840 textprintf_ex(screen, font, text_x, text_y, jwin_pal[jcTEXTFG], jwin_pal[jcBOX], "%s", text.c_str());
3841
3842 draw_text_button(screen,117*mul,(192+yofs)*mul,int32_t(61*(1.5)),int32_t(20*(1.5)),"Recolor",vc(1),vc(14),0,true);
3843 break;
3844 }
3845
3846 case ftZGP:
3847 case ftQST:
3848 case ftZQT:
3849 case ftQSU:
3850 case ftTIL:
3851 case ftBIN:
3852 textprintf_ex(screen,get_zc_font(font_lfont_l),txt_x,(216+yofs)*mul,jwin_pal[jcTEXTFG],jwin_pal[jcBOX],"%s %d KB",imgstr[imagetype],imagesize>>10);
3853 break;
3854 }
3855
3856 textprintf_ex(screen,font,txt_x,(168+yofs)*mul,jwin_pal[jcTEXTFG],jwin_pal[jcBOX],"sel: %d %d",selx,sely);
3857 textprintf_ex(screen,font,txt_x,(176+yofs)*mul,jwin_pal[jcTEXTFG],jwin_pal[jcBOX],"pos: %d %d",imagex,imagey);
3858
3859 if(bp==8)
3860 textprintf_ex(screen,font,txt_x,(192+yofs)*mul,jwin_pal[jcTEXTFG],jwin_pal[jcBOX],"8-bit");
3861 else
3862 textprintf_ex(screen,font,txt_x,(192+yofs)*mul,jwin_pal[jcTEXTFG],jwin_pal[jcBOX],"cset: %d",cs);
3863 textprintf_ex(screen,font,txt_x,(200+yofs)*mul,jwin_pal[jcTEXTFG],jwin_pal[jcBOX],"step: %d",grabmode);
3864
3865 if(imagetype==ftBIN)
3866 {
3867 textprintf_ex(screen,font,104*mul,(192+yofs)*mul,jwin_pal[jcTEXTFG],jwin_pal[jcBOX],"bp: %d%s",bp,nesmode?" (NES)":"");
3868 textprintf_ex(screen,font,104*mul,(200+yofs)*mul,jwin_pal[jcTEXTFG],jwin_pal[jcBOX],"ofs: %Xh",romofs);
3869 textprintf_ex(screen,font,104*mul,(208+yofs)*mul,jwin_pal[jcTEXTFG],jwin_pal[jcBOX],"m: %d",romtilemode);
3870 }
3871
3872 int fpath_y = (224+yofs)*mul;
3873 if(text_length(font,imagepath) <= max_fpath_wid)
3874 textout_ex(screen,font,imagepath,txt_x,fpath_y,jwin_pal[jcTEXTFG],jwin_pal[jcBOX]);
3875 else
3876 {
3877 char buf[2052] = {0};
3878 strncpy(buf,imagepath,2048);
3879 int len = strlen(buf);
3880 char *ptr = buf;
3881 char *endptr = buf+len;
3882 char *it = endptr;
3883 int tmpy = fpath_y;
3884 int tmph = text_height(font)+1;
3885 while(true)
3886 {
3887 if(tmpy+tmph > (winh-2))
3888 break; //Out of space!
3889 char c = *it;
3890 bool end = !c;
3891 *it = 0;
3892 int newlen = text_length(font,ptr);
3893 if(newlen <= (end ? max_fpath_wid : max_fpath_wid2))
3894 {
3895 if(end) //No stored character, string ended
3896 {
3897 textout_ex(screen,font,ptr,txt_x,tmpy,jwin_pal[jcTEXTFG],jwin_pal[jcBOX]);
3898 break;
3899 }
3900 char t[5];
3901 t[0] = c;
3902 for(int q = 1; q < 5; ++q)
3903 t[q] = it[q];
3904 strcpy(it,"...");
3905 textout_ex(screen,font,ptr,txt_x,tmpy,jwin_pal[jcTEXTFG],jwin_pal[jcBOX]);
3906 for(int q = 0; q < 5; ++q)
3907 it[q] = t[q];
3908 tmpy += tmph;
3909 ptr = it;
3910 it = endptr;
3911 }
3912 else
3913 {
3914 *it = c;
3915 --it;
3916 }
3917 }
3918 }
3919 draw_text_button(screen,rbtn_x,(168+yofs)*mul,int32_t(61*(1.5)),int32_t(20*(1.5)),"OK",vc(1),vc(14),0,true);
3920 draw_text_button(screen,rbtn_x,(192+yofs)*mul,int32_t(61*(1.5)),int32_t(20*(1.5)),"Cancel",vc(1),vc(14),0,true);
3921 draw_text_button(screen,rbtn_x,(216+yofs)*mul,int32_t(61*(1.5)),int32_t(20*(1.5)),"File",vc(1),vc(14),0,true);
3922 draw_text_button(screen,117*mul,(166+yofs)*mul,int32_t(61*(1.5)),int32_t(20*(1.5)),"Leech",vc(1),vc(14),0,true);
3923
3924 //int32_t rectw = 16*mul;
3925 //rect(screen,selx+screen_xofs,sely+screen_yofs,selx+screen_xofs+((width-1)*rectw)+rectw-1,sely+screen_yofs+((height-1)*rectw)+rectw-1,white);
3926 SCRFIX();
3927 font = oldfont;
3928 }
3929
3930 RGB_MAP rgb_table;
3931 COLOR_MAP imagepal_table;
3932
3933
3934 extern void return_RAMpal_color(AL_CONST PALETTE pal, int32_t x, int32_t y, RGB *rgb)
3935 {
3936 //these are here to bypass compiler warnings about unused arguments
3937 x=x;
3938
3939 rgb->r = pal[y].r;
3940 rgb->g = pal[y].g;
3941 rgb->b = pal[y].b;
3942 }
3943
3944
3945 void load_imagebuf()
3946 {
3947 PACKFILE *f;
3948 //cache QRS
3949 //byte cached_rules[QUESTRULES_NEW_SIZE] = { 0 };
3950 //for ( int32_t q = 0; q < QUESTRULES_NEW_SIZE; ++q )
3951 // {
3952 // cached_rules[q] = quest_rules[q];
3953 // }
3954 bool compressed=false;
3955 bool encrypted=false;
3956 tiledata *hold=newtilebuf;
3957 zquestheader tempheader;
3958 memset(&tempheader, 0, sizeof(zquestheader));
3959
3960 if(imagebuf)
3961 {
3962 switch(imagetype)
3963 {
3964 case ftBMP:
3965 if (original_imagebuf_bitmap != imagebuf)
3966 destroy_bitmap((BITMAP*)imagebuf);
3967 destroy_bitmap(original_imagebuf_bitmap);
3968 break;
3969
3970 case ftZGP:
3971 case ftQST:
3972 case ftZQT:
3973 case ftQSU:
3974 case ftTIL:
3975 clear_tiles(grabtilebuf);
3976 break;
3977
3978 case ftBIN:
3979 free(imagebuf);
3980 break;
3981 }
3982
3983 imagebuf=NULL;
3984 original_imagebuf_bitmap=NULL;
3985 }
3986
3987 selx=sely=romofs=0;
3988 bp=4;
3989 imagetype=filetype(imagepath);
3990
3991 dword section_id;
3992 dword section_version;
3993 dword section_cversion;
3994
3995 switch(imagetype)
3996 {
3997 case ftBMP:
3998 packfile_password("");
3999 memset(imagepal, 0, sizeof(PALETTE));
4000 original_imagebuf_bitmap = load_bitmap(imagepath,imagepal);
4001 imagesize = file_size_ex_password(imagepath,"");
4002 tilecount=0;
4003 create_rgb_table(&rgb_table, imagepal, NULL);
4004 rgb_map = &rgb_table;
4005 create_color_table(&imagepal_table, RAMpal, return_RAMpal_color, NULL);
4006
4007 if(!original_imagebuf_bitmap)
4008 {
4009 imagetype=0;
4010 }
4011 else
4012 {
4013 imagebuf = original_imagebuf_bitmap;
4014 imagebuf_bitmap_scale = 1;
4015 }
4016
4017 break;
4018
4019 case ftBIN:
4020 packfile_password("");
4021 imagesize = file_size_ex_password(imagepath, "");
4022 tilecount=0;
4023
4024 if(imagesize)
4025 {
4026 imagebuf = malloc(imagesize);
4027
4028 if(!readfile(imagepath,imagebuf,imagesize))
4029 {
4030 free(imagebuf);
4031 imagesize=0;
4032 imagetype=0;
4033 }
4034 }
4035
4036 break;
4037
4038 case ftTIL:
4039 packfile_password("");
4040 imagesize = file_size_ex_password(imagepath,"");
4041 f = pack_fopen_password(imagepath,F_READ,"");
4042
4043 if(!f)
4044 {
4045 goto error;
4046 }
4047
4048 if(!p_mgetl(&section_id,f))
4049 {
4050 goto error;
4051 }
4052
4053 if(section_id==ID_TILES)
4054 {
4055 if(readtiles(f, grabtilebuf, NULL, ZELDA_VERSION, VERSION_BUILD, 0, NEWMAXTILES, false)==0)
4056 {
4057 goto error;
4058 }
4059 }
4060
4061 error:
4062 pack_fclose(f);
4063 tilecount=count_tiles(grabtilebuf);
4064 break;
4065
4066 case ftZGP:
4067 packfile_password("");
4068 imagesize = file_size_ex_password(imagepath, "");
4069 f=pack_fopen_password(imagepath,F_READ,"");
4070
4071 if(!f)
4072 {
4073 goto error2;
4074 }
4075
4076 if(!p_mgetl(&section_id,f))
4077 {
4078 goto error2;
4079 }
4080
4081 if(section_id!=ID_GRAPHICSPACK)
4082 {
4083 goto error2;
4084 }
4085
4086 //section version info
4087 if(!p_igetw(&section_version,f))
4088 {
4089 goto error2;
4090 }
4091
4092 if(!p_igetw(&section_cversion,f))
4093 {
4094 goto error2;
4095 }
4096
4097 //tiles
4098 if(!p_mgetl(&section_id,f))
4099 {
4100 goto error2;
4101 }
4102
4103 if(section_id==ID_TILES)
4104 {
4105 if(readtiles(f, grabtilebuf, NULL, ZELDA_VERSION, VERSION_BUILD, 0, NEWMAXTILES, false)!=0)
4106 {
4107 goto error2;
4108 }
4109 }
4110
4111 error2:
4112 pack_fclose(f);
4113 tilecount=count_tiles(grabtilebuf);
4114 break;
4115
4116 case ftQST:
4117 encrypted=true;
4118 case ftZQT:
4119 compressed=true;
4120 case ftQSU:
4121 packfile_password("");
4122 imagesize = file_size_ex_password(imagepath, encrypted ? datapwd : "");
4123 newtilebuf=grabtilebuf;
4124 byte skip_flags[4];
4125
4126 for(int32_t i=0; i<skip_max; ++i)
4127 {
4128 set_bit(skip_flags,i,1);
4129 }
4130
4131 set_bit(skip_flags,skip_tiles,0);
4132 set_bit(skip_flags,skip_header,0);
4133 int ret = loadquest(imagepath,&tempheader,&QMisc,customtunes,true,skip_flags);
4134 if (ret)
4135 {
4136 imagetype=0;
4137 imagesize=0;
4138 clear_tiles(grabtilebuf);
4139 chop_path(imagepath);
4140 }
4141
4142 if (!ret && encrypted && compressed)
4143 {
4144 if(quest_access(imagepath, &tempheader) != 1)
4145 {
4146 imagetype=0;
4147 imagesize=0;
4148 clear_tiles(grabtilebuf);
4149 chop_path(imagepath);
4150 }
4151 }
4152
4153 //setPackfilePassword(NULL);
4154 newtilebuf=hold;
4155 tilecount=count_tiles(grabtilebuf);
4156 break;
4157 }
4158
4159 rgb_map = &zq_rgb_table;
4160 //restore cashed QRs / rules
4161
4162 //for ( int32_t q = 0; q < QUESTRULES_NEW_SIZE; ++q )
4163 // {
4164 // quest_rules[q] = cached_rules[q];
4165 // }
4166 }
4167
4168 static char bitstrbuf[32];
4169 bool leeching_from_tiles=false;
4170
4171 const char *bitlist(int32_t index, int32_t *list_size)
4172 {
4173 int32_t imported=2;
4174
4175 if(index>=0)
4176 {
4177 bound(index,0,leeching_from_tiles?2:1);
4178
4179 if(index==imported)
4180 {
4181 sprintf(bitstrbuf,"Imported");
4182 }
4183 else
4184 {
4185 sprintf(bitstrbuf,"%d",4<<index);
4186 }
4187
4188 return bitstrbuf;
4189 }
4190
4191 *list_size=leeching_from_tiles?3:2;
4192 return NULL;
4193 }
4194
4195 9 static ListData bit_list(bitlist, &font);
4196
4197 static DIALOG leech_dlg[] =
4198 {
4199 /* (dialog proc) (x) (y) (w) (h) (fg) (bg) (key) (flags) (d1) (d2) (dp) */
4200 9 { jwin_win_proc, 8, 20-4, 303+1, 216-42+1, vc(14), vc(1), 0, D_EXIT, 0, 0, (void *) "Leech Options", NULL, NULL },
4201 9 { d_timer_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL },
4202 // 2
4203 9 { jwin_button_proc, 180, 210-42-4, 61, 21, vc(14), vc(1), 27, D_EXIT, 0, 0, (void *) "Cancel", NULL, NULL },
4204 9 { jwin_button_proc, 80, 210-42-4, 61, 21, vc(14), vc(1), 13, D_EXIT, 0, 0, (void *) "OK", NULL, NULL },
4205 9 { d_keyboard_proc, 0, 0, 0, 0, 0, 0, 0, 0, KEY_F1, 0, (void *) onHelp, NULL, NULL },
4206 // 5
4207 9 { jwin_text_proc, 14, 49-4, 176, 8, vc(15), vc(1), 0, 0, 0, 0, (void *) "Update Status Every: ", NULL, NULL },
4208 9 { jwin_edit_proc, 114, 45-4, 36, 16, vc(12), vc(1), 0, 0, 5, 0, NULL, NULL, NULL },
4209 9 { jwin_radio_proc, 155, 49-4, 64+1, 8+1, vc(14), vc(1), 0, 0, 0, 0, (void *) "Tiles", NULL, NULL },
4210 9 { jwin_radio_proc, 200, 49-4, 64+1, 8+1, vc(14), vc(1), 0, 0, 0, 0, (void *) "Seconds", NULL, NULL },
4211 //9
4212 9 { jwin_frame_proc, 14, 63-2, 176+70, 50+30, jwin_pal[jcBOXFG], jwin_pal[jcBOX], 0, 0, FR_ETCHED, 0, NULL, NULL, NULL },
4213 9 { jwin_text_proc, 14+8, 60-2, 80, 8, vc(15), vc(1), 0, 0, 0, 0, (void *) " Duplicates ", NULL, NULL },
4214
4215 9 { jwin_check_proc, 20, 70, 168, 8+1, vc(15), vc(1), 0, 0, 1, 0, (void *) "Only check new tiles", NULL, NULL },
4216 9 { jwin_text_proc, 20, 90, 72, 8, vc(15), vc(1), 0, 0, 0, 0, (void *) "Normal:", NULL, NULL },
4217 9 { jwin_text_proc, 20, 100, 72, 8, vc(15), vc(1), 0, 0, 0, 0, (void *) "Horizontal Flip:", NULL, NULL },
4218 9 { jwin_text_proc, 20, 110, 72, 8, vc(15), vc(1), 0, 0, 0, 0, (void *) "Vertical Flip:", NULL, NULL },
4219 9 { jwin_text_proc, 20, 120, 72, 8, vc(15), vc(1), 0, 0, 0, 0, (void *) "Horizontal/Vertical Flip:", NULL, NULL },
4220 //16
4221 9 { jwin_radio_proc, 144, 90, 64+1, 8+1, vc(14), vc(1), 0, 0, 1, 0, NULL, NULL, NULL },
4222 9 { jwin_radio_proc, 184, 90, 56+1, 8+1, vc(14), vc(1), 0, 0, 1, 0, NULL, NULL, NULL },
4223 9 { jwin_radio_proc, 224, 90, 72+1, 8+1, vc(14), vc(1), 0, 0, 1, 0, NULL, NULL, NULL },
4224
4225 9 { jwin_radio_proc, 144, 100, 64+1, 8+1, vc(14), vc(1), 0, 0, 2, 0, NULL, NULL, NULL },
4226 9 { jwin_radio_proc, 184, 100, 56+1, 8+1, vc(14), vc(1), 0, 0, 2, 0, NULL, NULL, NULL },
4227 9 { jwin_radio_proc, 224, 100, 72+1, 8+1, vc(14), vc(1), 0, 0, 2, 0, NULL, NULL, NULL },
4228
4229 9 { jwin_radio_proc, 144, 110, 64+1, 8+1, vc(14), vc(1), 0, 0, 3, 0, NULL, NULL, NULL },
4230 9 { jwin_radio_proc, 184, 110, 56+1, 8+1, vc(14), vc(1), 0, 0, 3, 0, NULL, NULL, NULL },
4231 9 { jwin_radio_proc, 224, 110, 72+1, 8+1, vc(14), vc(1), 0, 0, 3, 0, NULL, NULL, NULL },
4232
4233 9 { jwin_radio_proc, 144, 120, 64+1, 8+1, vc(14), vc(1), 0, 0, 4, 0, NULL, NULL, NULL },
4234 9 { jwin_radio_proc, 184, 120, 56+1, 8+1, vc(14), vc(1), 0, 0, 4, 0, NULL, NULL, NULL },
4235 9 { jwin_radio_proc, 224, 120, 72+1, 8+1, vc(14), vc(1), 0, 0, 4, 0, NULL, NULL, NULL },
4236
4237 9 { jwin_ctext_proc, 144+4, 80, 64+1, 8+1, vc(14), vc(1), 0, 0, 0, 0, (void *) "Ignore", NULL, NULL },
4238 9 { jwin_ctext_proc, 184+4, 80, 56+1, 8+1, vc(14), vc(1), 0, 0, 0, 0, (void *) "Check", NULL, NULL },
4239 9 { jwin_ctext_proc, 224+4, 80, 72+1, 8+1, vc(14), vc(1), 0, 0, 0, 0, (void *) "Discard", NULL, NULL },
4240 9 { jwin_droplist_proc, 76, 145, 80, 16, jwin_pal[jcTEXTFG], jwin_pal[jcTEXTBG], 0, 0, 1, 0, (void *) &bit_list, NULL, NULL },
4241 9 { jwin_text_proc, 14, 149, 60, 8, vc(15), vc(1), 0, 0, 0, 0, (void *) "Color Depth: ", NULL, NULL },
4242 9 { NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }
4243 };
4244
4245 bool leech_tiles(tiledata *dest,int32_t start,int32_t cs)
4246 {
4247 bool shift=true; // fix this!
4248 int32_t cst=0;
4249 int32_t currtile=start;
4250 int32_t height=0, width=0;
4251 byte *testtile = new byte[tilesize(tf32Bit)];
4252 byte imported_format=0;
4253 char updatestring[6];
4254 bool canadd;
4255 bool temp_canadd;
4256 bool duplicate;
4257 int32_t total_duplicates_found=0, total_duplicates_discarded=0;
4258 int32_t duplicates_found[4]= //, duplicates_discarded[4]={0,0,0,0};
4259 {
4260 0,0,0,0
4261 };
4262 BITMAP *status;
4263 status = create_bitmap_ex(8,240,140);
4264 clear_bitmap(status);
4265 sprintf(updatestring, "%d", LeechUpdate);
4266 leech_dlg[0].dp2=get_zc_font(font_lfont);
4267 leech_dlg[6].dp=updatestring;
4268
4269 leech_dlg[10].flags=(OnlyCheckNewTilesForDuplicates!=0) ? D_SELECTED : 0;
4270
4271 for(int32_t i=0; i<2; i++)
4272 {
4273 leech_dlg[i+7].flags=0;
4274 }
4275
4276 leech_dlg[7+((LeechUpdateTiles==0) ? 1 : 0)].flags=D_SELECTED;
4277
4278 for(int32_t i=0; i<12; i++)
4279 {
4280 leech_dlg[i+16].flags=0;
4281 }
4282
4283 for(int32_t i=0; i<4; i++)
4284 {
4285 leech_dlg[(DuplicateAction[i])+16+(i*3)].flags=D_SELECTED;
4286 }
4287
4288 leech_dlg[31].d1=0;
4289
4290 large_dialog(leech_dlg);
4291
4292 int32_t ret = do_zqdialog(leech_dlg,3);
4293
4294 if(ret==2)
4295 {
4296 delete[] testtile;
4297 return false;
4298 }
4299
4300 int32_t cdepth=leech_dlg[31].d1+1;
4301 int32_t newformat=0;
4302 auto lu = atoi(updatestring);
4303 auto lut = (leech_dlg[7].flags&D_SELECTED)?1:0;
4304 if(LeechUpdate!=lu)
4305 {
4306 LeechUpdate=lu;
4307 zc_set_config("zquest","leech_update",LeechUpdate);
4308 }
4309 if(LeechUpdateTiles!=lut)
4310 {
4311 LeechUpdateTiles=lut;
4312 zc_set_config("zquest","leech_update_tiles",LeechUpdateTiles);
4313 }
4314
4315 int32_t old_dupe[4];
4316 for(int32_t j=0; j<4; j++)
4317 {
4318 old_dupe[j] = DuplicateAction[j];
4319 for(int32_t i=0; i<3; i++)
4320 {
4321 if(leech_dlg[i+16+(j*3)].flags&D_SELECTED)
4322 {
4323 DuplicateAction[j]=i;
4324 }
4325 }
4326 }
4327 if(old_dupe[0] != DuplicateAction[0])
4328 zc_set_config("zquest","normal_duplicate_action",DuplicateAction[0]);
4329 if(old_dupe[1] != DuplicateAction[1])
4330 zc_set_config("zquest","horizontal_duplicate_action",DuplicateAction[1]);
4331 if(old_dupe[2] != DuplicateAction[2])
4332 zc_set_config("zquest","vertical_duplicate_action",DuplicateAction[2]);
4333 if(old_dupe[3] != DuplicateAction[3])
4334 zc_set_config("zquest","both_duplicate_action",DuplicateAction[3]);
4335
4336 auto ocntfd = leech_dlg[10].flags&D_SELECTED?1:0;
4337 if(OnlyCheckNewTilesForDuplicates!=ocntfd)
4338 {
4339 OnlyCheckNewTilesForDuplicates=ocntfd;
4340 zc_set_config("zquest","only_check_new_tiles_for_duplicates",ocntfd);
4341 }
4342
4343 leeching_from_tiles=false;
4344
4345 switch(imagetype)
4346 {
4347 case ftBIN:
4348 width=imagesize/128;
4349 height=1;
4350 break;
4351
4352 case ftZGP:
4353 case ftQST:
4354 case ftZQT:
4355 case ftQSU:
4356 case ftTIL:
4357 leeching_from_tiles=true;
4358 width=count_tiles(grabtilebuf);
4359 height=1;
4360 break;
4361
4362 case ftBMP:
4363 width=((((BITMAP*)imagebuf)->w)+15)/16;
4364 height=((((BITMAP*)imagebuf)->h)+15)/16;
4365 break;
4366 }
4367
4368 if(currtile+(width*height)>NEWMAXTILES)
4369 {
4370 if(jwin_alert("Confirm Truncation","Too many tiles.","Truncation may occur.",NULL,"&OK","&Cancel",'o','c',get_zc_font(font_lfont))==2)
4371 {
4372 delete[] testtile;
4373 return false;
4374 }
4375 }
4376
4377 go_tiles();
4378 saved=false;
4379
4380 // usetiles=true;
4381 for(int32_t ty=0; ty<height; ty++) //for every row
4382 {
4383 for(int32_t tx=0; tx<width; tx++) //for every column (tile)
4384 {
4385 if((((ty*width)+tx)%zc_max(LeechUpdate, 1))==0) //update status
4386 {
4387 FONT *oldfont = font;
4388 static BITMAP *tbar = create_bitmap_ex(8,240-6, 18);
4389 static bool created_tbar=false;
4390 jwin_draw_win(status, 0, 0, 240, 140, FR_WIN);
4391
4392 if(created_tbar)
4393 {
4394 blit(tbar, status, 0, 0, 3, 3, 240-6, 18);
4395 }
4396 else
4397 {
4398 font = get_zc_font(font_lfont);
4399 jwin_draw_titlebar(tbar, 0, 0, 240-6, 18, "Leech Status", false);
4400 font = oldfont;
4401 created_tbar=true;
4402 blit(tbar, status, 0, 0, 3, 3, 320-6, 18);
4403 }
4404
4405 textprintf_centre_ex(status,font,120,24,jwin_pal[jcTEXTFG],-1,"Checking %d of %d",((ty*width)+tx), (width*height));
4406 textprintf_centre_ex(status,font,120,34,jwin_pal[jcTEXTFG],-1,"%d tiles imported",currtile-start);
4407 jwin_draw_frame(status, 40, 49, 160, 70, FR_ETCHED);
4408 textprintf_centre_ex(status,font,120,46,jwin_pal[jcTEXTFG],jwin_pal[jcBOX]," Duplicates ");
4409 textprintf_centre_ex(status,font,120,56,jwin_pal[jcTEXTFG],-1,"%d/%d found/discarded",total_duplicates_found, total_duplicates_discarded);
4410 textprintf_centre_ex(status,font,120,76,jwin_pal[jcTEXTFG],-1,"%d normal %s",duplicates_found[0],((DuplicateAction[0]<2)?"found":"discarded"));
4411 textprintf_centre_ex(status,font,120,86,jwin_pal[jcTEXTFG],-1,"%d flipped (h) %s",duplicates_found[1],((DuplicateAction[1]<2)?"found":"discarded"));
4412 textprintf_centre_ex(status,font,120,96,jwin_pal[jcTEXTFG],-1,"%d flipped (v) %s",duplicates_found[2],((DuplicateAction[2]<2)?"found":"discarded"));
4413 textprintf_centre_ex(status,font,120,106,jwin_pal[jcTEXTFG],-1,"%d flipped (hv) %s",duplicates_found[3],((DuplicateAction[3]<2)?"found":"discarded"));
4414 textprintf_centre_ex(status,font,120,128,jwin_pal[jcTEXTFG],-1,"Press any key to stop.");
4415 blit(status,screen,0, 0, 40, 20, 240, 140);
4416 SCRFIX();
4417 }
4418
4419 canadd=true;
4420
4421 if(currtile>=NEWMAXTILES) //if we've maxed out on our tiles...
4422 {
4423 delete[] testtile;
4424 return true;
4425 }
4426
4427 switch(imagetype)
4428 {
4429 case ftBIN:
4430 break;
4431
4432 case ftZGP:
4433 case ftQST:
4434 case ftZQT:
4435 case ftQSU:
4436 case ftTIL:
4437 memset(testtile, 0, tilesize(tf32Bit));
4438 imported_format=grabtilebuf[tx].format;
4439
4440 switch(cdepth)
4441 {
4442 case 1: //4-bit
4443 newformat=tf4Bit;
4444
4445 switch(imported_format)
4446 {
4447 case tf4Bit:
4448 case tf8Bit:
4449 for(int32_t y=0; y<16; y++) //snag a tile
4450 {
4451 for(int32_t x=0; x<16; x+=2)
4452 {
4453 testtile[(y*8)+(x/2)]=
4454 (grabtilebuf[tx].data[y*16+x]&15)+
4455 ((grabtilebuf[tx].data[y*16+x+1]&15)<<4);
4456 }
4457 }
4458
4459 break;
4460 }
4461
4462 break;
4463
4464 case 2: //8-bit
4465 newformat=tf8Bit;
4466
4467 switch(imported_format)
4468 {
4469 case tf4Bit:
4470 unpack_tile(grabtilebuf, tx, 0, true);
4471 cst = cs&15;
4472 cst <<= CSET_SHFT;
4473
4474 for(int32_t i=0; i<256; i++)
4475 {
4476 if(!shift||unpackbuf[i]!=0)
4477 {
4478 unpackbuf[i]+=cst;
4479 }
4480 }
4481
4482 pack_tiledata(testtile, unpackbuf, tf8Bit);
4483 break;
4484
4485 case tf8Bit:
4486 memcpy(testtile,grabtilebuf[tx].data,tilesize(imported_format));
4487 break;
4488 }
4489
4490 break;
4491
4492 case 3: //original tile's bit depth
4493 newformat=imported_format;
4494 memcpy(testtile,grabtilebuf[tx].data,tilesize(imported_format));
4495 break;
4496 }
4497
4498 break;
4499
4500 case ftBMP:
4501 newformat=cdepth;
4502
4503 for(int32_t y=0; y<16; y++) //snag a tile
4504 {
4505 for(int32_t x=0; x<16; x+=2)
4506 {
4507 testtile[(y*16)+x]=getpixel(((BITMAP*)imagebuf),(tx*16)+x,(ty*16)+y);
4508 testtile[(y*16)+x+1]=getpixel(((BITMAP*)imagebuf),(tx*16)+x+1,(ty*16)+y);
4509 }
4510 }
4511
4512 break;
4513 }
4514
4515 if(DuplicateAction[0]+DuplicateAction[1]+DuplicateAction[2]+DuplicateAction[3]>0)
4516 {
4517 temp_canadd=true;
4518
4519 //check all tiles before this one
4520 for(int32_t checktile=((OnlyCheckNewTilesForDuplicates!=0)?start:0); ((temp_canadd==true)&&(checktile<currtile)); checktile++)
4521 {
4522 for(int32_t flipping=0; ((temp_canadd==true)&&(flipping<4)); ++flipping)
4523 {
4524 if(DuplicateAction[flipping]>0)
4525 {
4526 if(keypressed())
4527 {
4528 delete[] testtile;
4529 return true;
4530 }
4531
4532 duplicate=(newformat==imported_format);
4533
4534 if(duplicate)
4535 {
4536 switch(flipping)
4537 {
4538 case 0: //normal
4539 if(dest[checktile].data!=NULL)
4540 {
4541 for(int32_t y=0; ((duplicate==true)&&(y<16)); y++)
4542 {
4543 for(int32_t x=0; ((duplicate==true)&&(x<16)); x+=3-newformat)
4544 {
4545 // if ((dest[(checktile*128)+(y*8)+(x/2)])!=(testtile[(y*8)+(x/2)]))
4546 if((dest[checktile].data[(y*8*newformat)+(x/(3-newformat))])!=testtile[(y*16)+x])
4547 {
4548 duplicate=false;
4549 }
4550 }
4551 }
4552 }
4553
4554 break;
4555
4556 case 1: //horizontal
4557 if(dest[checktile].data!=NULL)
4558 {
4559 for(int32_t y=0; ((duplicate==true)&&(y<16)); y++)
4560 {
4561 for(int32_t x=0; ((duplicate==true)&&(x<16)); x+=3-newformat)
4562 {
4563 // if ((dest[(checktile*128)+(y*8)+((14-x)/2)])!=(((testtile[(y*8)+(x/2)]&15)<<4)+((testtile[(y*8)+(x/2)]>>4)&15)))
4564 if((dest[checktile].data[(y*8*newformat)+(14+(newformat-1)-x)/(3-newformat)])!=testtile[(y*16)+x])
4565 {
4566 duplicate=false;
4567 }
4568 }
4569 }
4570 }
4571
4572 break;
4573
4574 case 2: //vertical
4575 if(dest[checktile].data!=NULL)
4576 {
4577 for(int32_t y=0; ((duplicate==true)&&(y<16)); y++)
4578 {
4579 for(int32_t x=0; ((duplicate==true)&&(x<16)); x+=3-newformat)
4580 {
4581 // if ((dest[(checktile*128)+((15-y)*8)+(x/2)])!=(testtile[(y*8)+(x/2)]))
4582 if((dest[checktile].data[((15-y)*8*newformat)+(x/(3-newformat))])!=testtile[(y*16)+x])
4583 {
4584 duplicate=false;
4585 }
4586 }
4587 }
4588 }
4589
4590 break;
4591
4592 case 3: //both
4593 if(dest[checktile].data!=NULL)
4594 {
4595 for(int32_t y=0; ((duplicate==true)&&(y<16)); y++)
4596 {
4597 for(int32_t x=0; ((duplicate==true)&&(x<16)); x+=3-newformat)
4598 {
4599 // if ((dest[(checktile*128)+((15-y)*8)+((14-x)/2)])!=(((testtile[(y*8)+(x/2)]&15)<<4)+((testtile[(y*8)+(x/2)]>>4)&15)))
4600 if((dest[checktile].data[((15-y)*8*newformat)+((14+(newformat-1)-x)/(3-newformat))])!=testtile[(y*16)+x])
4601 {
4602 duplicate=false;
4603 }
4604 }
4605 }
4606 }
4607
4608 break;
4609 }
4610 }
4611
4612 if(duplicate==true)
4613 {
4614 ++duplicates_found[flipping];
4615 ++total_duplicates_found;
4616
4617 if(DuplicateAction[flipping]>1)
4618 {
4619 ++total_duplicates_discarded;
4620 temp_canadd=false;
4621 }
4622 }
4623 }
4624
4625 canadd=canadd&&temp_canadd;
4626 }
4627 }
4628 }
4629
4630 // dest[currtile].format=(cdepth==3?imported_format:cdepth);
4631 dest[currtile].format=newformat;
4632
4633 if(dest[currtile].data!=NULL)
4634 {
4635 free(dest[currtile].data);
4636 }
4637
4638 dest[currtile].data=(byte *)malloc(tilesize(dest[currtile].format));
4639
4640 if(dest[currtile].data==NULL)
4641 {
4642 Z_error_fatal("Unable to initialize tile #%d.\n", currtile);
4643 }
4644
4645 if(canadd==true)
4646 {
4647 /*
4648 for(int32_t y=0; y<16; y++)
4649 {
4650 for(int32_t x=0; x<8; x++)
4651 {
4652 dest[currtile].data[(y*8)+x]=testtile[(y*8)+x];
4653 }
4654 }
4655 */
4656 memcpy(dest[currtile].data, testtile, tilesize(dest[currtile].format));
4657 ++currtile;
4658 }
4659 }
4660 }
4661
4662 destroy_bitmap(status);
4663 delete[] testtile;
4664 return true;
4665 }
4666
4667 void grab(byte(*dest)[256],byte *def, int32_t width, int32_t height, int32_t oformat, byte *newformat)
4668 {
4669 byte defFormat=(bp==8) ? tf8Bit : tf4Bit;
4670 byte format=defFormat;
4671 int32_t stile = ((imagey*TILES_PER_ROW)+imagex)+(((sely/16)*TILES_PER_ROW)+(selx/16));
4672
4673 switch(imagetype)
4674 {
4675 case ftZGP:
4676 case ftQST:
4677 case ftZQT:
4678 case ftQSU:
4679 case ftTIL:
4680 case ftBIN:
4681 case ftBMP:
4682 for(int32_t ty=0; ty<height; ty++)
4683 {
4684 for(int32_t tx=0; tx<width; tx++)
4685 {
4686 format=defFormat;
4687 switch(imagetype)
4688 {
4689 case ftZGP:
4690 case ftQST:
4691 case ftZQT:
4692 case ftQSU:
4693 case ftTIL:
4694 format=grabtilebuf[stile+((ty*TILES_PER_ROW)+tx)].format;
4695 break;
4696 }
4697
4698 bool ever_did_unmasked = false;
4699
4700 for(int32_t y=0; y<16; y++)
4701 {
4702 for(int32_t x=0; x<16; x+=2)
4703 {
4704 bool masked = (y<8 && x<8 && grabmask&1) || (y<8 && x>7 && grabmask&2) || (y>7 && x<8 && grabmask&4) || (y>7 && x>7 && grabmask&8);
4705 if (masked)
4706 {
4707 dest[(ty*TILES_PER_ROW)+tx][(y*16)+(x)]=def[(y*16)+(x)];
4708 dest[(ty*TILES_PER_ROW)+tx][(y*16)+(x+1)]=def[(y*16)+(x+1)];
4709 }
4710 else
4711 {
4712 dest[(ty*TILES_PER_ROW)+tx][(y*16)+x]=getpixel(screen2,(tx*16)+x+selx,(ty*16)+y+sely);
4713 dest[(ty*TILES_PER_ROW)+tx][(y*16)+x+1]=getpixel(screen2,(tx*16)+x+1+selx,(ty*16)+y+sely);
4714 ever_did_unmasked = true;
4715 }
4716 if (format == tf4Bit)
4717 {
4718 dest[(ty*TILES_PER_ROW)+tx][(y*16)+x] &= 15;
4719 dest[(ty*TILES_PER_ROW)+tx][(y*16)+x+1] &= 15;
4720 }
4721 }
4722 }
4723
4724 if (ever_did_unmasked)
4725 newformat[(ty*TILES_PER_ROW)+tx] = format;
4726 }
4727 }
4728
4729 break;
4730
4731 default:
4732 for(int32_t i=0; i<200; i++)
4733 {
4734 for(int32_t j=0; j<256; j++)
4735 {
4736 dest[i][j]=0;
4737 }
4738
4739 newformat[i] = tf4Bit;
4740 }
4741
4742 break;
4743 }
4744 }
4745
4746 static void scale_imagebuf_bitmap()
4747 {
4748 imagebuf_bitmap_scale = std::clamp(imagebuf_bitmap_scale, -10, 10);
4749
4750 float scale = IMAGEBUF_SCALE;
4751 int nw = original_imagebuf_bitmap->w * scale;
4752 int nh = original_imagebuf_bitmap->h * scale;
4753 if (nw <= 0 || nh <= 0)
4754 return;
4755
4756 BITMAP* scaled_bmp = create_bitmap_ex(8, nw, nh);
4757 if (!scaled_bmp)
4758 return;
4759
4760 stretch_blit(original_imagebuf_bitmap, scaled_bmp, 0, 0, original_imagebuf_bitmap->w, original_imagebuf_bitmap->h, 0, 0, nw, nh);
4761 if (imagebuf != original_imagebuf_bitmap)
4762 destroy_bitmap((BITMAP*)imagebuf);
4763 imagebuf = scaled_bmp;
4764 }
4765
4766 //Grabber is not grabbing to tile pages beyond pg. 252 right now. -ZX 18th June, 2019
4767 void grab_tile(int32_t tile,int32_t &cs)
4768 {
4769 zq_allow_tile_draw_cache = true;
4770
4771 int window_w = 640+6+6, window_h = 480+25+6;
4772 int window_x=(zq_screen_w-window_w)/2;
4773 int window_y=(zq_screen_h-window_h)/2;
4774 popup_zqdialog_start(window_x,window_y,window_w,window_h,-1);
4775 int window_xofs = 0;
4776 int screen_xofs=6;
4777 int screen_yofs=25;
4778 int panel_yofs=0;
4779 int bwidth = 61*1.5;
4780 int bheight = 20*1.5;
4781 int button_x = 255*2;
4782 int grab_ok_button_y = 168*2 + 32;
4783 int leech_button_x = 117*2;
4784 int leech_button_y = 166*2 + 32;
4785 int grab_cancel_button_y = 192*2 + 32;
4786 int file_button_y = 216*2 + 32;
4787 int rec_button_x = 117*2;
4788 int rec_button_y = 192*2 + 32;
4789
4790 int screen_y1 = 24;
4791 int screen_y2 = screen_y1+320-1;
4792
4793 int crect_x = 184+190;
4794 int crect_y = 168*2 + 32;
4795 int crect_w = 8*2;
4796 int crect_h = 8*2;
4797
4798 int xrect_x = 640 + 12 - 21;
4799 int xrect_y = 5;
4800
4801 byte newtile[200][256];
4802 BITMAP *screen3=create_bitmap_ex(8, zq_screen_w, zq_screen_h);
4803 clear_bitmap(screen3);
4804 byte newformat[200];
4805
4806 memset(newtile, 0, 200*256);
4807 memset(newformat, 0, 200);
4808
4809 static EXT_LIST list[] =
4810 {
4811 { (char *)"All Files (*.*)", NULL },
4812 { (char *)"Bitmap Image (*.bmp)", (char *)"bmp" },
4813 { (char *)"GIF Image (*.gif)", (char *)"gif" },
4814 { (char *)"JPEG Image (*.jpg, *.jpeg)", (char *)"jpg,jpeg" },
4815 { (char *)"ZC Tile Export (*.til)", (char *)"til" },
4816 { (char *)"ZC Quest Template (*.zqt)", (char *)"zqt" },
4817 { (char *)"ZC Quest (*.qst)", (char *)"qst" },
4818 { (char *)"ZC Graphics Pack (*.zgp)", (char *)"zgp" },
4819 { (char *)"ZC Unencoded Quest (*.qsu)", (char *)"qsu" },
4820 { (char *)"NES ROM Image (*.nes)", (char *)"nes" },
4821 { (char *)"SNES ROM Image (*.smc)", (char *)"smc" },
4822 { (char *)"Gameboy ROM Image (*.gb)", (char *)"gb" },
4823 { (char *)"Gameboy Advance ROM Image (*.gba)", (char *)"gba" },
4824 { NULL, NULL }
4825 };
4826
4827
4828 memset(cset_reduce_table, 0, 256);
4829 memset(col_diff,0,3*128);
4830 bool bdown=false;
4831 int done=0;
4832 int pal=0;
4833 int f=0;
4834 int black=vc(0),white=vc(15);
4835 int selwidth=1, selheight=1;
4836 int selx2=0, sely2=0;
4837 bool xreversed=false, yreversed=false;
4838 bool doleech=false, dofile=false, dopal=false;
4839
4840 int jwin_pal2[jcMAX];
4841 memcpy(jwin_pal2, jwin_pal, sizeof(int)*jcMAX);
4842
4843
4844 if(imagebuf==NULL)
4845 load_imagebuf();
4846
4847 calc_cset_reduce_table(imagepal, cs);
4848 calc_cset_reduce_table_8bit(imagepal);
4849 draw_grab_window();
4850 draw_grab_scr(tile,cs,newtile[0],black,white, selwidth, selheight, newformat);
4851 grab(newtile,newtilebuf[tile].data, selwidth, selheight, newtilebuf[tile].format, newformat);
4852
4853 while(gui_mouse_b())
4854 {
4855 /* do nothing */
4856 rest(1);
4857 }
4858
4859 do
4860 {
4861 HANDLE_CLOSE_ZQDLG();
4862 if(exiting_program) break;
4863 rest(4);
4864 bool redraw=false;
4865
4866 if(keypressed())
4867 {
4868 redraw=true;
4869
4870 switch(readkey()>>8)
4871 {
4872 case KEY_F:
4873 dofile=true;
4874 break;
4875
4876 case KEY_L:
4877 doleech=true;
4878 break;
4879
4880 case KEY_P:
4881 if(imagetype==ftBMP)
4882 {
4883 dopal=true;
4884 recolor=rcNone;
4885 calc_cset_reduce_table(imagepal, cs);
4886 }
4887
4888 break;
4889
4890 case KEY_ESC:
4891 done=1;
4892 break;
4893
4894 case KEY_ENTER_PAD:
4895 case KEY_ENTER:
4896 done=2;
4897 break;
4898
4899 case KEY_DOWN:
4900 if(CHECK_CTRL_CMD) sely=zc_min(sely+1,144);
4901 else ++imagey;
4902
4903 break;
4904
4905 case KEY_UP:
4906 if(CHECK_CTRL_CMD) sely=zc_max(sely-1,0);
4907 else --imagey;
4908
4909 break;
4910
4911 case KEY_RIGHT:
4912 if(CHECK_CTRL_CMD) selx=zc_min(selx+1,304);
4913 else ++imagex;
4914
4915 break;
4916
4917 case KEY_LEFT:
4918 if(CHECK_CTRL_CMD) selx=zc_max(selx-1,0);
4919 else --imagex;
4920
4921 break;
4922
4923 case KEY_PGDN:
4924 imagey+=10;
4925 break;
4926
4927 case KEY_PGUP:
4928 imagey-=10;
4929 break;
4930
4931 case KEY_HOME:
4932 imagex=imagey=0;
4933 break;
4934
4935 case KEY_EQUALS:
4936 case KEY_PLUS_PAD:
4937 cs = (cs<13) ? cs+1:0;
4938 if(recolor==rc4Bit)
4939 calc_cset_reduce_table(imagepal, cs);
4940 break;
4941
4942 case KEY_MINUS:
4943 case KEY_MINUS_PAD:
4944 cs = (cs>0) ? cs-1:13;
4945 if(recolor==rc4Bit)
4946 calc_cset_reduce_table(imagepal, cs);
4947 break;
4948
4949 case KEY_S:
4950 if(grabmode==1) grabmode=8;
4951 else if(grabmode==8) grabmode=16;
4952 else grabmode=1;
4953
4954 break;
4955
4956 case KEY_COMMA:
4957 if (imagetype == ftBMP)
4958 {
4959 imagebuf_bitmap_scale--;
4960 if (imagebuf_bitmap_scale == 0)
4961 imagebuf_bitmap_scale = -2;
4962 scale_imagebuf_bitmap();
4963 }
4964 break;
4965 case KEY_STOP:
4966 if (imagetype == ftBMP)
4967 {
4968 imagebuf_bitmap_scale++;
4969 if (imagebuf_bitmap_scale == -1)
4970 imagebuf_bitmap_scale = 1;
4971 scale_imagebuf_bitmap();
4972 }
4973 break;
4974
4975 case KEY_1:
4976 if(recolor==rc8Bit)
4977 recolor=rcNone;
4978 //imagex=(imagex*bp)>>3;
4979 bp=1;
4980 //imagex<<=3;
4981 nesmode=false;
4982 break;
4983
4984 case KEY_2:
4985 if(recolor==rc8Bit)
4986 recolor=rcNone;
4987 //imagex=(imagex*bp)>>3;
4988 bp=2;
4989 //imagex<<=2;
4990 nesmode=false;
4991 break;
4992
4993 case KEY_N:
4994 if(recolor==rc8Bit)
4995 recolor=rcNone;
4996 //imagex=(imagex*bp)>>3;
4997 bp=2;
4998 //imagex<<=2;
4999 nesmode=true;
5000 break;
5001
5002 case KEY_4:
5003 if(recolor==rc8Bit)
5004 recolor=rcNone;
5005 //imagex=(imagex*bp)>>3;
5006 bp=4;
5007 //imagex<<=1;
5008 nesmode=false;
5009 break;
5010
5011 case KEY_8:
5012 //imagex=(imagex*bp)>>3;
5013 bp=8;
5014 break;
5015
5016 case KEY_B:
5017 if(bp==2&&!nesmode)
5018 {
5019 nesmode=true;
5020 }
5021 else
5022 {
5023 nesmode=false;
5024 bp<<=1;
5025
5026 if(bp==16)
5027 {
5028 bp=1;
5029 //imagex<<=3;
5030 }
5031 else
5032 {
5033 //imagex>>=1;
5034 }
5035 }
5036
5037 break;
5038
5039 case KEY_M:
5040 romtilemode=(romtilemode+1)%4;
5041 break;
5042
5043 case KEY_Z:
5044 if(romofs>0) --romofs;
5045
5046 break;
5047
5048 case KEY_X:
5049 ++romofs;
5050 break;
5051
5052 case KEY_R:
5053 if(pal)
5054 {
5055 dopal=true;
5056 }
5057
5058 if(recolor!=rcNone)
5059 recolor=rcNone;
5060 else if(key[KEY_LSHIFT] || key[KEY_RSHIFT])
5061 {
5062 bp=8;
5063 recolor=rc8Bit;
5064 calc_cset_reduce_table_8bit(imagepal);
5065 }
5066 else
5067 {
5068 if(bp==8)
5069 bp=4;
5070 recolor=rc4Bit;
5071 calc_cset_reduce_table(imagepal, cs);
5072 }
5073 break;
5074
5075 default:
5076 redraw=false;
5077 }
5078
5079 clear_keybuf();
5080
5081 if(imagex<0) imagex=0;
5082
5083 if(imagey<0) imagey=0;
5084
5085 draw_grab_scr(tile,cs,newtile[0],black,white, selwidth, selheight, newformat);
5086 grab(newtile,newtilebuf[tile].data, selwidth, selheight, newtilebuf[tile].format, newformat);
5087 }
5088
5089 //boogie!
5090 if(gui_mouse_b()==1 && !bdown)
5091 {
5092 int x=gui_mouse_x();
5093 int y=gui_mouse_y();
5094 if(isinRect(x,y,xrect_x, xrect_y, xrect_x + 15, xrect_y + 13))
5095 if(do_x_button(screen, xrect_x, xrect_y))
5096 done=1;
5097
5098 if(!bdown)
5099 {
5100 bool regrab=false;
5101 bdown=true;
5102 FONT* oldfont = font;
5103 font = get_zc_font(font_lfont_l);
5104
5105 if(y>=screen_y1 && y<=screen_y2)
5106 {
5107 do
5108 {
5109 HANDLE_CLOSE_ZQDLG();
5110 if(exiting_program) break;
5111 int x = (gui_mouse_x()-screen_xofs) / 2;
5112 int y = (gui_mouse_y()-screen_yofs) / 2;
5113
5114 int ox=selx,oy=sely,ow=selwidth,oh=selheight;
5115
5116 if(!(key[KEY_LSHIFT] || key[KEY_RSHIFT]))
5117 {
5118 selx=vbound((x/grabmode)*grabmode,0,304);
5119 sely=vbound((y/grabmode)*grabmode,0,144);
5120 selx2=selx;
5121 sely2=sely;
5122 selwidth=1;
5123 selheight=1;
5124 xreversed=false;
5125 yreversed=false;
5126 }
5127 else
5128 {
5129 if(xreversed)
5130 {
5131 zc_swap(selx, selx2);
5132 xreversed=false;
5133 }
5134
5135 if(yreversed)
5136 {
5137 zc_swap(sely, sely2);
5138 yreversed=false;
5139 }
5140
5141 selx2=vbound((x/grabmode)*grabmode,0,304);
5142 sely2=vbound((y/grabmode)*grabmode,0,144);
5143 selwidth=1+(abs(selx2-selx))/16;
5144 selheight=1+(abs(sely2-sely))/16;
5145
5146 if(selx2<selx)
5147 {
5148 zc_swap(selx, selx2);
5149 xreversed=true;
5150 }
5151
5152 if(sely2<sely)
5153 {
5154 zc_swap(sely, sely2);
5155 yreversed=true;
5156 }
5157 }
5158
5159 bool changed = (ox!=selx || oy!=sely || ow!=selwidth || oh!=selheight);
5160 bool redraw = changed || !(f%8);
5161
5162 if(redraw)
5163 {
5164 draw_grab_scr(tile,cs,newtile[0],black,white, selwidth, selheight, newformat);
5165 if(changed)
5166 grab(newtile,newtilebuf[tile].data, selwidth, selheight, newtilebuf[tile].format, newformat);
5167 if(f&8)
5168 {
5169 static const int w = 32;
5170 rect(screen,(selx*2)+screen_xofs,(sely*2)+screen_yofs,(selx*2)+screen_xofs+((selwidth-1)*w)+(w-1),(sely*2)+screen_yofs+((selheight-1)*w)+(w-1),white);
5171 }
5172 }
5173 else custom_vsync();
5174
5175 ++f;
5176 }
5177 while(gui_mouse_b());
5178 }
5179 else if(isinRect(x,y,button_x,grab_ok_button_y,button_x+bwidth,grab_ok_button_y+bheight))
5180 {
5181 if(do_text_button(button_x,grab_ok_button_y,bwidth,bheight,"OK"))
5182 done=2;
5183 }
5184 else if(isinRect(x,y,leech_button_x,leech_button_y,leech_button_x+bwidth,leech_button_y+bheight))
5185 {
5186 if(do_text_button(leech_button_x,leech_button_y,bwidth,bheight,"Leech"))
5187 {
5188 doleech=true;
5189 }
5190 }
5191 else if(isinRect(x,y,button_x,grab_cancel_button_y,button_x+bwidth,grab_cancel_button_y+bheight))
5192 {
5193 if(do_text_button(button_x,grab_cancel_button_y,bwidth,bheight,"Cancel"))
5194 done=1;
5195 }
5196 else if(isinRect(x,y,button_x,file_button_y,button_x+bwidth,file_button_y+bheight))
5197 {
5198 if(do_text_button(button_x,file_button_y,bwidth,bheight,"File"))
5199 {
5200 dofile=true;
5201 }
5202 }
5203 else if(imagetype == ftBMP && isinRect(x,y,rec_button_x, rec_button_y, rec_button_x+bwidth, rec_button_y+bheight))
5204 {
5205 if(do_text_button(rec_button_x,rec_button_y,bwidth,bheight,"Recolor"))
5206 {
5207 if(pal)
5208 {
5209 dopal = true;
5210 }
5211
5212 if(recolor!=rcNone)
5213 recolor=rcNone;
5214 else if(key[KEY_LSHIFT] || key[KEY_RSHIFT])
5215 {
5216 bp=8;
5217 recolor=rc8Bit;
5218 calc_cset_reduce_table_8bit(imagepal);
5219 }
5220 else
5221 {
5222 if(bp==8)
5223 bp=4;
5224 recolor=rc4Bit;
5225 calc_cset_reduce_table(imagepal, cs);
5226 }
5227 redraw=true;
5228 }
5229 }
5230 else if(isinRect(x,y+panel_yofs,crect_x,crect_y,crect_x+(16),crect_y+crect_h-1))
5231 {
5232 regrab=true;
5233 grabmask^=1;
5234 }
5235 else if(isinRect(x,y+panel_yofs,crect_x+crect_w,crect_y,crect_x+(32)-1,crect_y+crect_h-1))
5236 {
5237 regrab=true;
5238 grabmask^=2;
5239 }
5240 else if(isinRect(x,y+panel_yofs,crect_x,crect_y+crect_h,crect_x+(16)-1,crect_y+crect_h+crect_h-1))
5241 {
5242 regrab=true;
5243 grabmask^=4;
5244 }
5245 else if(isinRect(x,y+panel_yofs,crect_x+crect_w,crect_y+crect_h,crect_x+(32)-1,crect_y+crect_h+crect_h-1))
5246 {
5247 regrab=true;
5248 grabmask^=8;
5249 }
5250
5251 if(regrab)
5252 {
5253 draw_grab_scr(tile,cs,newtile[0],black,white, selwidth, selheight, newformat);
5254 grab(newtile,newtilebuf[tile].data, selwidth, selheight, newtilebuf[tile].format, newformat);
5255 redraw=true;
5256 }
5257
5258 font = oldfont;
5259 }
5260 }
5261
5262 if(gui_mouse_b()==0)
5263 bdown=false;
5264
5265 if(dofile)
5266 {
5267 if (prompt_for_existing_file_compat("Load File", "", list, imagepath, true))
5268 {
5269 zc_set_palette(RAMpal);
5270 pal=0;
5271 white=vc(15);
5272 black=vc(0);
5273 strcpy(imagepath,temppath);
5274 load_imagebuf();
5275 imagex=imagey=0;
5276 calc_cset_reduce_table(imagepal, cs);
5277 draw_grab_scr(tile,cs,newtile[0],black,white, selwidth, selheight, newformat);
5278 grab(newtile,newtilebuf[tile].data, selwidth, selheight, newtilebuf[tile].format, newformat);
5279 }
5280
5281 while(key[KEY_ESC])
5282 {
5283 poll_keyboard();
5284 /* do nothing */
5285 rest(1);
5286 }
5287
5288 clear_keybuf();
5289 dofile=false;
5290 redraw=true;
5291 }
5292
5293 if(doleech)
5294 {
5295 if(leech_tiles(newtilebuf,tile,cs))
5296 {
5297 done=1;
5298 }
5299 else
5300 {
5301 while(key[KEY_ESC])
5302 {
5303 poll_keyboard();
5304 /* do nothing */
5305 rest(1);
5306 }
5307
5308 clear_keybuf();
5309 redraw=true;
5310 }
5311
5312 doleech=false;
5313 }
5314
5315 if(dopal)
5316 {
5317 pal^=1;
5318
5319 if(pal)
5320 {
5321 get_bw(imagepal,black,white);
5322
5323 jwin_pal[jcBOX] =imagepal_table.data[0][jwin_pal[jcBOX]];
5324 jwin_pal[jcLIGHT] =imagepal_table.data[0][jwin_pal[jcLIGHT]];
5325 jwin_pal[jcMEDLT] =imagepal_table.data[0][jwin_pal[jcMEDLT]];
5326 jwin_pal[jcMEDDARK]=imagepal_table.data[0][jwin_pal[jcMEDDARK]];
5327 jwin_pal[jcDARK] =imagepal_table.data[0][jwin_pal[jcDARK]];
5328 jwin_pal[jcBOXFG] =imagepal_table.data[0][jwin_pal[jcBOXFG]];
5329 jwin_pal[jcTITLEL] =imagepal_table.data[0][jwin_pal[jcTITLEL]];
5330 jwin_pal[jcTITLER] =imagepal_table.data[0][jwin_pal[jcTITLER]];
5331 jwin_pal[jcTITLEFG]=imagepal_table.data[0][jwin_pal[jcTITLEFG]];
5332 jwin_pal[jcTEXTBG] =imagepal_table.data[0][jwin_pal[jcTEXTBG]];
5333 jwin_pal[jcTEXTFG] =imagepal_table.data[0][jwin_pal[jcTEXTFG]];
5334 jwin_pal[jcSELBG] =imagepal_table.data[0][jwin_pal[jcSELBG]];
5335 jwin_pal[jcSELFG] =imagepal_table.data[0][jwin_pal[jcSELFG]];
5336 gui_bg_color=jwin_pal[jcBOX];
5337 gui_fg_color=jwin_pal[jcBOXFG];
5338 jwin_set_colors(jwin_pal);
5339 }
5340 else
5341 {
5342 white=vc(15);
5343 black=vc(0);
5344
5345 memcpy(jwin_pal, jwin_pal2, sizeof(int)*jcMAX);
5346 gui_bg_color=jwin_pal[jcBOX];
5347 gui_fg_color=jwin_pal[jcBOXFG];
5348 jwin_set_colors(jwin_pal);
5349 }
5350
5351 zc_set_palette_range(pal?imagepal:RAMpal,0,255,false);
5352
5353 dopal=false;
5354 redraw=true;
5355 }
5356
5357 if(redraw)
5358 {
5359 draw_grab_scr(tile,cs,newtile[0],black,white, selwidth, selheight, newformat);
5360 }
5361 else
5362 {
5363 custom_vsync();
5364 }
5365
5366 if((f%8)==0)
5367 {
5368 stretch_blit(screen2,screen3,0, 0, zq_screen_w, zq_screen_h, 0, 0, zq_screen_w*2, zq_screen_h*2);
5369
5370 int selxl = selx* 2;
5371 int selyl = sely* 2;
5372 int w = 32;
5373
5374 if(f&8)
5375 rect(screen3,selxl,selyl,selxl+((selwidth-1)*w)+(w-1),selyl+((selheight-1)*w)+(w-1),white);
5376
5377 blit(screen3,screen,selxl,selyl,selxl+screen_xofs,selyl+screen_yofs,selwidth*w,selheight*w);
5378 }
5379
5380 // SCRFIX();
5381 ++f;
5382
5383 }
5384 while(!done);
5385
5386 memcpy(jwin_pal, jwin_pal2, sizeof(int)*jcMAX);
5387 gui_bg_color=jwin_pal[jcBOX];
5388 gui_fg_color=jwin_pal[jcBOXFG];
5389 jwin_set_colors(jwin_pal);
5390
5391
5392 if(done==2)
5393 {
5394 go_tiles();
5395 saved=false;
5396
5397 // usetiles=true;
5398 for(int y=0; y<selheight; y++)
5399 {
5400 for(int x=0; x<selwidth; x++)
5401 {
5402 int temptile=tile+((TILES_PER_ROW*y)+x);
5403 int format=(bp==8) ? tf8Bit : tf4Bit;
5404
5405 if(newtilebuf[temptile].data!=NULL)
5406 free(newtilebuf[temptile].data);
5407
5408 newtilebuf[temptile].format=format;
5409 newtilebuf[temptile].data=(byte *)malloc(tilesize(format));
5410
5411 if(newtilebuf[temptile].data==NULL)
5412 {
5413 Z_error_fatal("Unable to initialize tile #%d.\n", temptile);
5414 break;
5415 }
5416
5417 for(int i=0; i<256; i++)
5418 {
5419 // newtilebuf[temptile].data[i] = cset_reduce_table[newtile[(TILES_PER_ROW*y)+x][i]];
5420 newtilebuf[temptile].data[i] = newtile[(TILES_PER_ROW*y)+x][i];
5421 }
5422
5423 // unpackbuf[i]=(cset_reduce_table[unpackbuf[i]]);
5424 }
5425 }
5426 }
5427
5428 destroy_bitmap(screen3);
5429
5430 if(pal)
5431 zc_set_palette(RAMpal);
5432
5433 recolor=rcNone;
5434 calc_cset_reduce_table(imagepal, cs);
5435 register_blank_tiles();
5436 popup_zqdialog_end();
5437
5438 zq_allow_tile_draw_cache = false;
5439 }
5440
5441 int32_t show_only_unused_tiles=4; //1 bit: hide used, 2 bit: hide unused, 4 bit: hide blank
5442 bool tile_is_used(int32_t tile)
5443 {
5444 return used_tile_table[tile];
5445 }
5446 void draw_tiles(int32_t first,int32_t cs, int32_t f)
5447 {
5448 draw_tiles(screen2, first, cs, f, true);
5449 }
5450 void draw_tiles(BITMAP* dest,int32_t first,int32_t cs, int32_t f, bool large, bool true_empty)
5451 {
5452 clear_bitmap(dest);
5453 BITMAP *buf = create_bitmap_ex(8,16,16);
5454
5455 int32_t w = 16;
5456 int32_t h = 16;
5457
5458 if(large)
5459 {
5460 w *=2;
5461 h *=2;
5462 }
5463
5464 for(int32_t i=0; i<TILES_PER_PAGE; i++) // 13 rows, leaving 32 pixels from y=208 to y=239
5465 {
5466 int32_t x = (i%TILES_PER_ROW)<<4;
5467 int32_t y = (i/TILES_PER_ROW)<<4;
5468 int32_t l = 16;
5469
5470 if(large)
5471 {
5472 x*=2;
5473 y*=2;
5474 l*=2;
5475 }
5476
5477 l-=2;
5478
5479 if((HIDE_USED && tile_is_used(first+i) && !blank_tile_table[first+i]) // 1 bit: hide used
5480 || (HIDE_UNUSED && !tile_is_used(first+i) && !blank_tile_table[first+i]) // 2 bit: hide unused
5481 || (HIDE_BLANK && blank_tile_table[first+i])) // 4 bit: hide blank
5482 {
5483 if(!true_empty) //Use pure color 0; no effects
5484 {
5485 if (InvalidBG == 2)
5486 {
5487 draw_checkerboard(dest, x, y, w);
5488 }
5489 else if(InvalidBG == 1)
5490 {
5491 for(int32_t dy=0; dy<=l+1; dy++)
5492 {
5493 for(int32_t dx=0; dx<=l+1; dx++)
5494 {
5495 dest->line[dy+(y)][dx+(x)]=vc((((zc_oldrand()%100)/50)?0:8)+(((zc_oldrand()%100)/50)?0:7));
5496 }
5497 }
5498 }
5499 else
5500 {
5501 for(int32_t dy=0; dy<=l+1; dy++)
5502 {
5503 for(int32_t dx=0; dx<=l+1; dx++)
5504 {
5505 dest->line[dy+(y)][dx+(x)]=vc(0);
5506 }
5507 }
5508 rect(dest, (x)+1,(y)+1, (x)+l, (y)+l, vc(15));
5509 line(dest, (x)+1,(y)+1, (x)+l, (y)+l, vc(15));
5510 line(dest, (x)+1,(y)+l, (x)+l, (y)+1, vc(15));
5511 }
5512 }
5513 }
5514 else
5515 {
5516 puttile16(buf,first+i,0,0,cs,0);
5517 stretch_blit(buf,dest,0,0,16,16,x,y,w,h);
5518 }
5519
5520 if((f%32)<=16 && large && !HIDE_8BIT_MARKER && newtilebuf[first+i].format==tf8Bit)
5521 {
5522 textprintf_ex(dest,get_zc_font(font_z3smallfont),(x)+l-3,(y)+l-3,vc(int32_t((f%32)/6)+10),-1,"8");
5523 }
5524 }
5525
5526 destroy_bitmap(buf);
5527 }
5528
5529 void tile_info_0(int32_t tile,int32_t tile2,int32_t cs,int32_t copy,int32_t copycnt,int32_t page,bool rect_sel)
5530 {
5531 int32_t yofs=3;
5532 BITMAP *buf = create_bitmap_ex(8,16,16);
5533 int32_t mul = 2;
5534 FONT *tfont = get_zc_font(font_pfont);
5535
5536 rectfill(screen2,0,210*2,(320*2)-1,(240*2),jwin_pal[jcBOX]);
5537 hline(screen2, 0, (210*2)-2, (320*2)-1, jwin_pal[jcMEDLT]);
5538 hline(screen2, 0, (210*2)-1, (320*2)-1, jwin_pal[jcLIGHT]);
5539 tfont = get_zc_font(font_lfont_l);
5540
5541 // Copied tile and numbers
5542 jwin_draw_frame(screen2,(34*mul)-2,((216*mul)+yofs)-2,(16*mul)+4,(16*mul)+4,FR_DEEP);
5543 int32_t coldiff=TILECOL(copy)-TILECOL(copy+copycnt-1);
5544 if(copy>=0)
5545 {
5546 puttile16(buf,rect_sel&&coldiff>0?copy-coldiff:copy,0,0,cs,0);
5547 stretch_blit(buf,screen2,0,0,16,16,34*mul,216*mul+yofs,16*mul,16*mul);
5548
5549 if(copycnt>1)
5550 {
5551 textprintf_right_ex(screen2,tfont,28*mul,(216*mul)+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d-",copy);
5552 textprintf_right_ex(screen2,tfont,24*mul,(224*mul)+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d",copy+copycnt-1);
5553 }
5554 else
5555 {
5556 textprintf_right_ex(screen2,tfont,24*mul,(220*mul)+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d",copy);
5557 }
5558 }
5559 else // No tiles copied
5560 {
5561 if (InvalidBG == 2)
5562 {
5563 draw_checkerboard(screen2, 34 * mul, 216 * mul + yofs, 16 * mul);
5564 }
5565 else if(InvalidBG == 1)
5566 {
5567 for(int32_t dy=0; dy<16*mul; dy++)
5568 {
5569 for(int32_t dx=0; dx<16*mul; dx++)
5570 {
5571 screen2->line[(216*mul+yofs+dy)][36*mul+dx]=vc((((zc_oldrand()%100)/50)?0:8)+(((zc_oldrand()%100)/50)?0:7));
5572 }
5573 }
5574 }
5575 else
5576 {
5577 rectfill(screen2, 34*mul, (216*mul)+yofs, (34+15)*mul, ((216+15)*mul)+yofs, vc(0));
5578 rect(screen2, 34*mul, (216*mul)+yofs, (34+15)*mul, ((216+15)*mul)+yofs, vc(15));
5579 line(screen2, 34*mul, (216*mul)+yofs, (34+15)*mul, ((216+15)*mul)+yofs, vc(15));
5580 line(screen2, 34*mul, ((216+15)*mul)+yofs, (34+15)*mul, (216*mul)+yofs, vc(15));
5581 }
5582 }
5583
5584
5585 // Current tile
5586 jwin_draw_frame(screen2,(104*mul)-2,(216*mul+yofs)-2,(16*mul)+4,(16*mul)+4,FR_DEEP);
5587 puttile16(buf,tile,0,0,cs,0);
5588 stretch_blit(buf,screen2,0,0,16,16,104*mul,216*mul+yofs,16*mul,16*mul);
5589
5590 // Current selection mode
5591 jwin_draw_frame(screen2,(127*mul)-2,(216*mul+yofs)-2,(16*mul)+4,(16*mul)+4,FR_DEEP);
5592 stretch_blit(select_bmp[rect_sel?1:0],screen2,0,0,16,16,127*mul,216*mul+yofs,16*mul,16*mul);
5593
5594 if(tile>tile2)
5595 {
5596 zc_swap(tile,tile2);
5597 }
5598
5599 char tbuf[8];
5600 tbuf[0]=0;
5601
5602 if(tile2!=tile)
5603 {
5604 sprintf(tbuf,"-%d",tile2);
5605 }
5606
5607 // Current tile and CSet text
5608 textprintf_ex(screen2,tfont,55*mul,216*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"cs: %d",cs);
5609 textprintf_right_ex(screen2,tfont,99*mul,216*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"tile:");
5610 textprintf_right_ex(screen2,tfont,99*mul,224*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d%s",tile,tbuf);
5611
5612 FONT *tf = font;
5613 font = tfont;
5614
5615 draw_text_button(screen2,150*mul,213*mul+yofs,28*mul,21*mul,"&Grab",jwin_pal[jcBOXFG],jwin_pal[jcBOX],0,true);
5616 draw_text_button(screen2,(150+28)*mul,213*mul+yofs,28*mul,21*mul,"&Edit",jwin_pal[jcBOXFG],jwin_pal[jcBOX],0,true);
5617 draw_text_button(screen2,(150+28*2)*mul,213*mul+yofs,28*mul,21*mul,"Export",jwin_pal[jcBOXFG],jwin_pal[jcBOX],0,true);
5618 draw_text_button(screen2,(150+28*3)*mul,213*mul+yofs,28*mul,21*mul,"Recolor",jwin_pal[jcBOXFG],jwin_pal[jcBOX],0,true);
5619 draw_text_button(screen2,(150+28*4)*mul,213*mul+yofs,28*mul,21*mul,"Done",jwin_pal[jcBOXFG],jwin_pal[jcBOX],0,true);
5620
5621 jwin_draw_icon(screen2,(305*mul+4),220*mul-6+yofs,jwin_pal[jcBOXFG],BTNICON_ARROW_UP,6,true);
5622 textprintf_ex(screen2,tfont,293*mul,220*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"p:");
5623 textprintf_centre_ex(screen2,tfont,(305*mul+4),220*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d",page);
5624 jwin_draw_icon(screen2,(305*mul+4),228*mul+3+yofs,jwin_pal[jcBOXFG],BTNICON_ARROW_DOWN,6,true);
5625
5626 font = tf;
5627
5628 int32_t w = 640;
5629 int32_t h = 480;
5630 int32_t window_xofs=(zq_screen_w-w-12)>>1;
5631 int32_t window_yofs=(zq_screen_h-h-25-6)>>1;
5632 int32_t screen_xofs=window_xofs+6;
5633 int32_t screen_yofs=window_yofs+25;
5634
5635 custom_vsync();
5636 blit(screen2,screen,0,0,screen_xofs,screen_yofs,w,h);
5637 SCRFIX();
5638 destroy_bitmap(buf);
5639 }
5640
5641 void tile_info_1(int32_t oldtile,int32_t oldflip,int32_t oldcs,int32_t tile,int32_t flip,int32_t cs,int32_t copy,int32_t page, bool always_use_flip)
5642 {
5643 int32_t yofs=3;
5644 BITMAP *buf = create_bitmap_ex(8,16,16);
5645 int32_t mul = 2;
5646 FONT *tfont = get_zc_font(font_pfont);
5647
5648 rectfill(screen2,0,210*2,(320*2)-1,(240*2),jwin_pal[jcBOX]);
5649 hline(screen2, 0, (210*2)-2, (320*2)-1, jwin_pal[jcMEDLT]);
5650 hline(screen2, 0, (210*2)-1, (320*2)-1, jwin_pal[jcLIGHT]);
5651 tfont = get_zc_font(font_lfont_l);
5652
5653 jwin_draw_frame(screen2,(124*mul)-2,((216*mul)+yofs)-2,(16*mul)+4,(16*mul)+4,FR_DEEP);
5654
5655 if(copy>=0)
5656 {
5657 puttile16(buf,copy,0,0,cs,flip);
5658 stretch_blit(buf,screen2,0,0,16,16,124*mul,216*mul+yofs,16*mul,16*mul);
5659 }
5660 else
5661 {
5662 if (InvalidBG == 2)
5663 {
5664 draw_checkerboard(screen2, 124 * mul, 216 * mul + yofs, 16 * mul);
5665 }
5666 else if(InvalidBG == 1)
5667 {
5668 for(int32_t dy=0; dy<16*mul; dy++)
5669 {
5670 for(int32_t dx=0; dx<16*mul; dx++)
5671 {
5672 screen2->line[216*mul+yofs+dy][124*mul+dx]=vc((((zc_oldrand()%100)/50)?0:8)+(((zc_oldrand()%100)/50)?0:7));
5673 }
5674 }
5675 }
5676 else
5677 {
5678 rectfill(screen2, 124*mul, (216*mul)+yofs, (124+15)*mul, ((216+15)*mul)+yofs, vc(0));
5679 rect(screen2, 124*mul, (216*mul)+yofs, (124+15)*mul, ((216+15)*mul)+yofs, vc(15));
5680 line(screen2, 124*mul, (216*mul)+yofs, (124+15)*mul, ((216+15)*mul)+yofs, vc(15));
5681 line(screen2, 124*mul, ((216+15)*mul)+yofs, (124+15)*mul, (216*mul)+yofs, vc(15));
5682 }
5683 }
5684
5685 jwin_draw_frame(screen2,(8*mul)-2,(216*mul+yofs)-2,(16*mul)+4,(16*mul)+4,FR_DEEP);
5686 puttile16(buf,oldtile,0,0, oldcs, oldflip);
5687 stretch_blit(buf,screen2,0,0,16,16,8*mul,216*mul+yofs,16*mul,16*mul);
5688
5689 textprintf_right_ex(screen2,tfont,56*mul,212*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"Old Tile:");
5690 textprintf_ex(screen2,tfont,60*mul,212*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d",oldtile);
5691
5692 textprintf_right_ex(screen2,tfont,56*mul,220*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"CSet:");
5693 textprintf_ex(screen2,tfont,60*mul,220*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d",oldcs);
5694
5695 if(oldflip > 0 || always_use_flip) // Suppress Flip for this usage
5696 {
5697 textprintf_right_ex(screen2,tfont,56*mul,228*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"Flip:");
5698 textprintf_ex(screen2,tfont,60*mul,228*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d",oldflip);
5699 }
5700
5701 jwin_draw_frame(screen2,(148*mul)-2,(216*mul+yofs)-2,(16*mul)+4,(16*mul)+4,FR_DEEP);
5702 puttile16(buf,tile,0,0, cs,
5703 (oldflip>0 || always_use_flip)?flip:0); // Suppress Flip for this usage
5704 stretch_blit(buf,screen2,0,0,16,16,148*mul,216*mul+yofs,16*mul,16*mul);
5705
5706 textprintf_right_ex(screen2,tfont,201*mul,212*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"New Tile:");
5707 textprintf_ex(screen2,tfont,205*mul,212*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d",tile);
5708 textprintf_right_ex(screen2,tfont,201*mul,220*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"CSet:");
5709 textprintf_ex(screen2,tfont,205*mul,220*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d",cs);
5710
5711 if(oldflip > 0 || always_use_flip) // Suppress Flip for this usage
5712 {
5713 textprintf_right_ex(screen2,tfont,201*mul,228*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"Flip:");
5714 textprintf_ex(screen2,tfont,205*mul,228*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d",flip);
5715 }
5716
5717 jwin_draw_icon(screen2,(305*mul+4),220*mul-6+yofs,jwin_pal[jcBOXFG],BTNICON_ARROW_UP,6,true);
5718 textprintf_ex(screen2,tfont,293*mul,220*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"p:");
5719 textprintf_centre_ex(screen2,tfont,309*mul,220*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d",page);
5720 jwin_draw_icon(screen2,(305*mul+4),228*mul+3+yofs,jwin_pal[jcBOXFG],BTNICON_ARROW_DOWN,6,true);
5721
5722
5723 int32_t w = 640;
5724 int32_t h = 480;
5725 int32_t window_xofs=(zq_screen_w-w-12)>>1;
5726 int32_t window_yofs=(zq_screen_h-h-25-6)>>1;
5727 int32_t screen_xofs=window_xofs+6;
5728 int32_t screen_yofs=window_yofs+25;
5729
5730 custom_vsync();
5731 blit(screen2,screen,0,0,screen_xofs,screen_yofs,w,h);
5732 SCRFIX();
5733 destroy_bitmap(buf);
5734 }
5735 /*
5736 void reset_tile(tiledata *buf, int32_t t, int32_t format=1)
5737 {
5738 buf[t].format=format;
5739 if (buf[t].data!=NULL)
5740 {
5741 free(buf[t].data);
5742 }
5743 buf[t].data=(byte *)malloc(tilesize(buf[t].format));
5744 if (buf[t].data==NULL)
5745 {
5746 Z_error_fatal("Unable to initialize tile #%d.\n", t);
5747 }
5748 for(int32_t i=0; i<tilesize(buf[t].format); i++)
5749 {
5750 buf[t].data[i]=0;
5751 }
5752 }
5753 */
5754
5755 int32_t hide_used()
5756 {
5757 show_only_unused_tiles ^= 1;
5758 return D_O_K;
5759 }
5760 int32_t hide_unused()
5761 {
5762 show_only_unused_tiles ^= 2;
5763 return D_O_K;
5764 }
5765 int32_t hide_blank()
5766 {
5767 show_only_unused_tiles ^= 4;
5768 return D_O_K;
5769 }
5770 int32_t hide_8bit_marker()
5771 {
5772 show_only_unused_tiles ^= 8;
5773 return D_O_K;
5774 }
5775
5776 enum
5777 {
5778 MENUID_SELTILE_VIEW_HIDE_USED,
5779 MENUID_SELTILE_VIEW_HIDE_UNUSED,
5780 MENUID_SELTILE_VIEW_HIDE_BLANK,
5781 MENUID_SELTILE_VIEW_HIDE_8BIT,
5782 };
5783
1/4
✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
9 static NewMenu select_tile_view_menu
5784 45 {
5785
2/4
✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9 times.
✗ Branch 3 not taken.
9 { "Hide Used", hide_used, MENUID_SELTILE_VIEW_HIDE_USED },
5786
2/4
✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9 times.
✗ Branch 3 not taken.
9 { "Hide Unused", hide_unused, MENUID_SELTILE_VIEW_HIDE_UNUSED },
5787
2/4
✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9 times.
✗ Branch 3 not taken.
9 { "Hide Blank", hide_blank, MENUID_SELTILE_VIEW_HIDE_BLANK },
5788
2/4
✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9 times.
✗ Branch 3 not taken.
9 { "Hide 8-bit marker", hide_8bit_marker, MENUID_SELTILE_VIEW_HIDE_8BIT },
5789 };
5790
5791 9 static std::function<void(int)> select_tile_color_depth_cb;
5792
5793 static void set_tile_color_depth_4()
5794 {
5795 select_tile_color_depth_cb(tf4Bit);
5796 }
5797 static void set_tile_color_depth_8()
5798 {
5799 select_tile_color_depth_cb(tf8Bit);
5800 }
5801 enum
5802 {
5803 MENUID_SELTILE_COLOR_DEPTH_4_BIT,
5804 MENUID_SELTILE_COLOR_DEPTH_8_BIT,
5805 };
5806
1/4
✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
9 static NewMenu select_tile_color_depth_menu
5807 27 {
5808
2/4
✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9 times.
✗ Branch 3 not taken.
9 { "4-bit", set_tile_color_depth_4, MENUID_SELTILE_COLOR_DEPTH_4_BIT },
5809
2/4
✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9 times.
✗ Branch 3 not taken.
9 { "8-bit", set_tile_color_depth_8, MENUID_SELTILE_COLOR_DEPTH_8_BIT },
5810 };
5811
5812 //returns the row the tile is in on its page
5813 int32_t tile_page_row(int32_t tile)
5814 {
5815 return TILEROW(tile)-(TILEPAGE(tile)*TILE_ROWS_PER_PAGE);
5816 }
5817
5818 enum {ti_none, ti_encompass, ti_broken};
5819
5820 //striped check and striped selection
5821 int32_t move_intersection_ss(newcombo &cmb, int32_t selection_first, int32_t selection_last, int32_t offset = 0)
5822 {
5823 int32_t cmb_first = cmb.o_tile;
5824 int32_t cmb_last = cmb.o_tile;
5825 do
5826 {
5827 cmb_last = cmb.tile;
5828 animate(cmb, true);
5829 }
5830 while(cmb.tile != cmb.o_tile);
5831 reset_combo_animation(cmb);
5832 cmb_first += offset;
5833 cmb_last += offset;
5834
5835 if(cmb_first > selection_last || cmb_last < selection_first)
5836 return ti_none;
5837 if(cmb_first >= selection_first && cmb_last <= selection_last)
5838 return ti_encompass;
5839
5840 do
5841 {
5842 if(cmb.tile+offset >= selection_first && cmb.tile+offset <= selection_last)
5843 {
5844 reset_combo_animation(cmb);
5845 return ti_broken; //contained, but non-encompassing.
5846 }
5847 animate(cmb, true);
5848 }
5849 while(cmb.tile != cmb.o_tile);
5850 reset_combo_animation(cmb);
5851 return ti_none;
5852 }
5853 int32_t move_intersection_ss(int32_t check_first, int32_t check_last, int32_t selection_first, int32_t selection_last)
5854 {
5855 // if selection is before or after check...
5856 if((check_first>selection_last)||(selection_first>check_last))
5857 {
5858 return ti_none;
5859 }
5860
5861 // if selection envelopes check
5862 if((selection_first<=check_first)&&(selection_last>=check_last))
5863 {
5864 return ti_encompass; //encompass
5865 }
5866
5867 //everything else is a break
5868 return ti_broken; //intersect
5869 }
5870
5871
5872
5873 //rectangular check and striped selection
5874 int32_t move_intersection_rs(int32_t check_left, int32_t check_top, int32_t check_width, int32_t check_height, int32_t selection_first, int32_t selection_last)
5875 {
5876 int32_t ret1=-1, ret2=-1;
5877
5878 for(int32_t i=0; i<check_height; ++i)
5879 {
5880 int32_t check_first=((check_top+i)*TILES_PER_ROW)+check_left;
5881 int32_t check_last=check_first+check_width-1;
5882 ret2=move_intersection_ss(check_first, check_last, selection_first, selection_last);
5883
5884 if(ret2==ti_broken)
5885 {
5886 return ti_broken;
5887 }
5888
5889 ret1=(ret2==ti_encompass?ti_encompass:ret1);
5890 }
5891
5892 if(ret1==ti_encompass)
5893 {
5894 if((TILEROW(selection_first)<=check_top) &&
5895 (TILEROW(selection_last)>=(check_top+check_height-1)))
5896 {
5897 return ti_encompass;
5898 }
5899 else
5900 {
5901 return ti_broken;
5902 }
5903 }
5904
5905 return ti_none;
5906 }
5907
5908
5909 //striped check and rectangular selection
5910 int32_t move_intersection_sr(newcombo &cmb, int32_t selection_left, int32_t selection_top, int32_t selection_width, int32_t selection_height, int32_t offset = 0)
5911 {
5912 if(selection_width < TILES_PER_ROW)
5913 {
5914 int32_t cmb_first = cmb.o_tile;
5915 int32_t cmb_last = cmb.o_tile;
5916 do
5917 {
5918 cmb_last = cmb.tile;
5919 animate(cmb, true);
5920 }
5921 while(cmb.tile != cmb.o_tile);
5922 reset_combo_animation(cmb);
5923 cmb_first += offset;
5924 cmb_last += offset;
5925
5926 if((TILEROW(cmb_first)>=selection_top) &&
5927 (TILEROW(cmb_last)<=selection_top+selection_height-1) &&
5928 (TILECOL(cmb_first)>=selection_left) &&
5929 (TILECOL(cmb_last)<=TILECOL(selection_left+selection_width-1)))
5930 {
5931 return ti_encompass;
5932 }
5933 else if((cmb_last<selection_top*TILES_PER_ROW+selection_left) ||
5934 (cmb_first>(selection_top+selection_height-1)*TILES_PER_ROW+selection_left+selection_width-1))
5935 {
5936 return ti_none;
5937 }
5938
5939 if(TILEROW(cmb_first) == TILEROW(cmb_last))
5940 {
5941 int32_t firstcol = TILECOL(cmb_first);
5942 int32_t lastcol = TILECOL(cmb_last);
5943
5944 if(lastcol < selection_left || firstcol >= selection_left+selection_width)
5945 return ti_none;
5946 else //handle skip x
5947 {
5948 do
5949 {
5950 if(TILECOL(cmb.tile) >= selection_left && TILECOL(cmb.tile) <= selection_left+selection_width)
5951 {
5952 reset_combo_animation(cmb);
5953 return ti_broken;
5954 }
5955 animate(cmb, true);
5956 }
5957 while(cmb.tile != cmb.o_tile);
5958 reset_combo_animation(cmb);
5959 return ti_none;
5960 }
5961 }
5962 else //multi-row combo...
5963 {
5964 int32_t row = TILEROW(cmb_first);
5965
5966 do
5967 {
5968 if(row < selection_top || row > selection_top+selection_height-1)
5969 {
5970 //This row isn't in the selection; skip to next row
5971 do
5972 {
5973 animate(cmb,true);
5974 if(cmb.tile == cmb.o_tile) return ti_none; //reached end
5975 }
5976 while(TILEROW(cmb.tile) == row);
5977 row = TILEROW(cmb.tile);
5978 continue;
5979 }
5980
5981 //This row IS in the selection; check each tile.
5982 do
5983 {
5984 if(TILECOL(cmb.tile) >= selection_left && TILECOL(cmb.tile) <= selection_left+selection_width-1)
5985 {
5986 reset_combo_animation(cmb);
5987 return ti_broken;
5988 }
5989 animate(cmb, true);
5990 if(cmb.tile == cmb.o_tile) return ti_none; //reached end
5991 }
5992 while(TILEROW(cmb.tile) == row);
5993 row = TILEROW(cmb.tile);
5994 }
5995 while(cmb.tile != cmb.o_tile);
5996
5997 return ti_none; //...Theoretically unreachable, but if it DOES get here, it's done.
5998 }
5999 }
6000
6001 return move_intersection_ss(cmb, selection_top*TILES_PER_ROW+selection_left, (selection_top+selection_height-1)*TILES_PER_ROW+selection_left+selection_width-1, offset);
6002 }
6003 int32_t move_intersection_sr(int32_t check_first, int32_t check_last, int32_t selection_left, int32_t selection_top, int32_t selection_width, int32_t selection_height)
6004 {
6005 if(selection_width < TILES_PER_ROW)
6006 {
6007 if((check_last-check_first+1<=selection_width) &&
6008 (TILEROW(check_first)>=selection_top) &&
6009 (TILEROW(check_last)<=selection_top+selection_height-1) &&
6010 (TILECOL(check_first)>=selection_left) &&
6011 (TILECOL(check_last)<=TILECOL(selection_left+selection_width-1)))
6012 {
6013 return ti_encompass;
6014 }
6015 else if((check_last<selection_top*TILES_PER_ROW+selection_left) ||
6016 (check_first>(selection_top+selection_height-1)*TILES_PER_ROW+selection_left+selection_width-1))
6017 {
6018 return ti_none;
6019 }
6020
6021 //else if (selection_top*TILES_PER_ROW+selection_left<check_first && (selection_top+1)*TILES_PER_ROW+selection_left>check_last)
6022
6023 //one last base case: the strip we're interested in only lies along one row
6024 if(check_first/TILES_PER_ROW == check_last/TILES_PER_ROW)
6025 {
6026 int32_t cfcol = check_first%TILES_PER_ROW;
6027 int32_t clcol = check_last%TILES_PER_ROW;
6028
6029 if(clcol < selection_left || cfcol >= selection_left+selection_width)
6030 return ti_none;
6031 else
6032 return ti_broken;
6033 }
6034 else
6035 {
6036 //recursively cut the strip into substrips which lie entirely on one row
6037 int32_t currow = check_first/TILES_PER_ROW;
6038 int32_t endrow = check_last/TILES_PER_ROW;
6039 int32_t accum = 0;
6040 accum |= move_intersection_sr(check_first,(currow+1)*TILES_PER_ROW-1,selection_left,selection_top,selection_width,selection_height);
6041
6042 for(++currow; currow<endrow; currow++)
6043 {
6044 accum |= move_intersection_sr(currow*TILES_PER_ROW,(currow+1)*TILES_PER_ROW-1,selection_left,selection_top,selection_width,selection_height);
6045 }
6046
6047 accum |= move_intersection_sr(currow*TILES_PER_ROW, check_last,selection_left,selection_top,selection_width,selection_height);
6048
6049 if(accum > 0)
6050 return ti_broken;
6051
6052 return ti_none;
6053 }
6054 }
6055
6056 return move_intersection_ss(check_first, check_last, selection_top*TILES_PER_ROW+selection_left, (selection_top+selection_height-1)*TILES_PER_ROW+selection_left+selection_width-1);
6057 }
6058
6059 //rectangular check and rectangular selection
6060 int32_t move_intersection_rr(int32_t check_left, int32_t check_top, int32_t check_width, int32_t check_height, int32_t selection_left, int32_t selection_top, int32_t selection_width, int32_t selection_height)
6061 {
6062 if((check_left>=selection_left) &&
6063 (check_left+check_width<=selection_left+selection_width) &&
6064 (check_top>=selection_top) &&
6065 (check_top+check_height<=selection_top+selection_height))
6066 {
6067 return ti_encompass;
6068 }
6069 else
6070 {
6071 for(int32_t i=check_top; i<check_top+check_height; ++i)
6072 {
6073 if(move_intersection_rs(selection_left, selection_top, selection_width, selection_height, i*TILES_PER_ROW+check_left, i*TILES_PER_ROW+check_left+check_width-1)!=ti_none)
6074 {
6075 return ti_broken;
6076 }
6077 }
6078 }
6079
6080 return ti_none;
6081 }
6082
6083
6084
6085
6086 static DIALOG move_textbox_list_dlg[] =
6087 {
6088 // (dialog proc) (x) (y) (w) (h) (fg) (bg) (key) (flags) (d1) (d2) (dp)
6089 9 { jwin_win_proc, 0, 0, 300, 212, vc(14), vc(1), 0, D_EXIT, 0, 0, NULL, NULL, NULL },
6090 9 { jwin_ctext_proc, 150, 18, 0, 8, vc(15), vc(1), 0, 0, 0, 0, (void *) "", NULL, NULL },
6091 9 { jwin_ctext_proc, 150, 28, 0, 8, vc(15), vc(1), 0, 0, 0, 0, (void *) "", NULL, NULL },
6092 9 { jwin_textbox_proc, 12, 40, 277, 138, jwin_pal[jcTEXTFG], jwin_pal[jcTEXTBG], 0, D_EXIT, 0, 0, NULL, NULL, NULL },
6093 9 { jwin_button_proc, 80, 185, 61, 21, vc(14), vc(1), 13, D_EXIT, 0, 0, (void *) "OK", NULL, NULL },
6094 9 { jwin_button_proc, 160, 185, 61, 21, vc(14), vc(1), 13, D_EXIT, 0, 0, (void *) "Cancel", NULL, NULL },
6095 9 { d_timer_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL },
6096 9 { NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }
6097 };
6098
6099 bool popup_move_textbox_dlg(string const& msg, char* textbox, char const* title)
6100 {
6101 char buf1[512] = {0};
6102 char buf2[512] = {0};
6103 large_dialog(move_textbox_list_dlg);
6104 DIALOG& tbox = move_textbox_list_dlg[3];
6105 {
6106 FONT* f = tbox.dp2 ? (FONT*)tbox.dp2 : get_custom_font(CFONT_GUI);
6107 int indx = 0, word_indx = 0;
6108 for(char c : msg)
6109 {
6110 if(c == ' ' || c == '\n')
6111 word_indx = indx;
6112 buf1[indx++] = c;
6113 if(c == '\n' || text_length(f, buf1) >= tbox.w)
6114 {
6115 buf1[word_indx] = 0;
6116 strcpy(buf2, msg.c_str()+word_indx+1);
6117 break;
6118 }
6119 }
6120 }
6121
6122 move_textbox_list_dlg[0].dp = (void*)title;
6123 move_textbox_list_dlg[0].dp2 = get_zc_font(font_lfont);
6124 move_textbox_list_dlg[1].dp = buf1;
6125 move_textbox_list_dlg[2].dp = buf2;
6126 tbox.dp = textbox;
6127 tbox.d2 = 0;
6128 auto tby = tbox.y;
6129 auto tbh = tbox.h;
6130 if(!buf2[0])
6131 {
6132 auto diff = move_textbox_list_dlg[2].h;
6133 tbox.y -= diff;
6134 tbox.h += diff;
6135 }
6136
6137 int32_t ret=do_zqdialog(move_textbox_list_dlg,2);
6138 position_mouse_z(0);
6139 tbox.y = tby;
6140 tbox.h = tbh;
6141
6142 return ret == 4;
6143 }
6144
6145 int32_t quick_select_3(int32_t a, int32_t b, int32_t c, int32_t d)
6146 {
6147 return a==0?b:a==1?c:d;
6148 }
6149
6150 bool TileMoveList::process(std::unique_ptr<BaseTileRef>& ref, TileMoveProcess const& proc, bool is_dest)
6151 {
6152 TileRefCombo* combo_ref = dynamic_cast<TileRefCombo*>(ref.get());
6153 int i = ti_none;
6154 auto t = ref->getTile() + ref->offset();
6155
6156 if(combo_ref)
6157 {
6158 if(proc.rect)
6159 i=move_intersection_sr(*combo_ref->combo, proc._l, proc._t, proc._w, proc._h);
6160 else i=move_intersection_ss(*combo_ref->combo, proc._first, proc._last);
6161 }
6162 else if(proc.rect)
6163 {
6164 if(ref->h > 1)
6165 i=move_intersection_rr(TILECOL(t), TILEROW(t), ref->w, ref->h, proc._l, proc._t, proc._w, proc._h);
6166 else i=move_intersection_sr(t, t+ref->w-1, proc._l, proc._t, proc._w, proc._h);
6167 }
6168 else
6169 {
6170 if(ref->h > 1)
6171 i=move_intersection_rs(TILECOL(t), TILEROW(t), ref->w, ref->h, proc._first, proc._last);
6172 else i=move_intersection_ss(t, t+ref->w-1, proc._first, proc._last);
6173 }
6174
6175 bool in = i != ti_none, out = i != ti_encompass;
6176 for(size_t q = 0; !(in&&out) && q < ref->extra_rects.size(); ++q)
6177 {
6178 auto [ex_t,ex_w,ex_h] = ref->extra_rects[q];
6179 if(proc.rect)
6180 i = move_intersection_rr(TILECOL(t+ex_t), TILEROW(t+ex_t), ex_w, ex_h, proc._l, proc._t, proc._w, proc._h);
6181 else i = move_intersection_rs(TILECOL(t+ex_t), TILEROW(t+ex_t), ex_w, ex_h, proc._first, proc._last);
6182 if(i != ti_none)
6183 in = true;
6184 if(i != ti_encompass)
6185 out = true;
6186 }
6187 i = in ? (out ? ti_broken : ti_encompass) : ti_none;
6188
6189 if(i != ti_none && ref->getTile() != 0)
6190 {
6191 if(mode == Mode::CHECK_ALL)
6192 {
6193 move_refs.emplace_back(std::move(ref));
6194 return true;
6195 }
6196 else if(i==ti_broken || is_dest || (i==ti_encompass && ref->no_move))
6197 {
6198 if(warning_flood || warning_list.tellp() >= 65000)
6199 {
6200 if(!warning_flood)
6201 warning_list << "...\n...\n...\nmany others";
6202 warning_flood = true;
6203 }
6204 else
6205 warning_list << ref->name << '\n';
6206 }
6207 else if(i==ti_encompass)
6208 {
6209 move_refs.emplace_back(std::move(ref));
6210 return true;
6211 }
6212 }
6213 return false;
6214 }
6215
6216 bool TileMoveList::check_prot()
6217 {
6218 if(!TileProtection)
6219 return true;
6220 auto ret = !warning_list.tellp() || popup_move_textbox_dlg(msg, warning_list.str().data(), "Tile Warning");
6221
6222 warning_flood = false;
6223 warning_list.clear();
6224
6225 return ret;
6226 }
6227
6228 void TileMoveList::add_diff(int diff)
6229 {
6230 for(auto& ref : move_refs)
6231 ref->addTile(diff);
6232 }
6233
6234 //from 'combo.h'
6235 bool ComboMoveList::process(std::unique_ptr<BaseComboRef>& ref, ComboMoveProcess const& proc, bool is_dest)
6236 {
6237 int i = ti_none;
6238 auto c = ref->getCombo();
6239
6240 if(ref->no_move)
6241 processed_combos[c] = true;
6242 else processed_combos[c]; //inserts element if does not exist
6243 i = move_intersection_ss(c, c, proc._first, proc._last);
6244
6245 if(i != ti_none && ref->getCombo() != 0)
6246 {
6247 if(i==ti_broken || is_dest || (i==ti_encompass && ref->no_move))
6248 {
6249 if(ComboProtection)
6250 {
6251 if(warning_flood || warning_list.tellp() >= 65000)
6252 {
6253 if(!warning_flood)
6254 warning_list << "...\n...\n...\nmany others";
6255 warning_flood = true;
6256 }
6257 else
6258 warning_list << ref->name << '\n';
6259 }
6260 }
6261 else if(i==ti_encompass)
6262 {
6263 move_refs.emplace_back(std::move(ref));
6264 return true;
6265 }
6266 }
6267 return false;
6268 }
6269
6270 bool ComboMoveList::check_prot()
6271 {
6272 if(!ComboProtection)
6273 return true;
6274 vector<set<int> const*> subset = combo_links.subset(processed_combos);
6275 bool subset_header = false;
6276 for(int q = 0; q < 2; ++q)
6277 {
6278 bool is_dest = (q==1);
6279 if(!is_dest && !source_process)
6280 continue;
6281 ComboMoveProcess const& proc = is_dest ? dest_process : *source_process;
6282 for(auto it = subset.begin(); it != subset.end();)
6283 {
6284 auto s = *it;
6285 if(warning_flood || warning_list.tellp() >= 65000)
6286 {
6287 if(!warning_flood)
6288 warning_list << "...\n...\n...\nmany others";
6289 warning_flood = true;
6290 break;
6291 }
6292 set<int> in_set, out_set;
6293 bool no_move = is_dest;
6294 for(int c : *s)
6295 {
6296 int i = move_intersection_ss(c, c, proc._first, proc._last);
6297 if(i != ti_none)
6298 in_set.insert(c);
6299 if(i != ti_encompass)
6300 out_set.insert(c);
6301 if(!no_move)
6302 {
6303 auto it = processed_combos.find(c);
6304 if(it != processed_combos.end() && it->second)
6305 no_move = true;
6306 }
6307 }
6308 int i = in_set.empty() ? ti_none : (out_set.empty() ? ti_encompass : ti_broken);
6309 if(i == ti_encompass && !no_move)
6310 {
6311 it = subset.erase(it);
6312 continue;
6313 }
6314 if(i == ti_none)
6315 {
6316 ++it;
6317 continue;
6318 }
6319
6320 if(!subset_header)
6321 {
6322 subset_header = true;
6323 warning_list << "===== Broken Relative Combo Groups =====\n";
6324 }
6325 bool comma = false;
6326 warning_list << "In(";
6327 for(int c : in_set)
6328 {
6329 if(comma)
6330 warning_list << ",";
6331 else comma = true;
6332 warning_list << c;
6333 }
6334 warning_list << "),Out(";
6335 comma = false;
6336 for(int c : out_set)
6337 {
6338 if(comma)
6339 warning_list << ",";
6340 else comma = true;
6341 warning_list << c;
6342 }
6343 warning_list << ")\n";
6344 it = subset.erase(it);
6345 }
6346 }
6347 auto ret = !warning_list.tellp() || popup_move_textbox_dlg(msg, warning_list.str().data(), "Combo Warning");
6348
6349 processed_combos.clear();
6350 warning_flood = false;
6351 warning_list.clear();
6352
6353 return ret;
6354 }
6355
6356 void ComboMoveList::add_diff(int diff)
6357 {
6358 for(auto& ref : move_refs)
6359 ref->addCombo(diff);
6360 }
6361
6362 static void collect_subscreen_tiles(SubscrWidget& widget, TileMoveList& list)
6363 {
6364 if (auto w = dynamic_cast<SW_2x2Frame*>(&widget))
6365 {
6366 list.add_tile(&w->tile, 2, 2, "2x2 Frame");
6367 }
6368 else if (auto w = dynamic_cast<SW_TriFrame*>(&widget))
6369 {
6370 list.add_tile(&w->frame_tile, 6, 3, "McGuffin Frame - Frame");
6371 list.add_tile(&w->piece_tile, "McGuffin Frame - Piece");
6372 }
6373 else if (auto w = dynamic_cast<SW_McGuffin*>(&widget))
6374 {
6375 list.add_tile(&w->tile, "McGuffin Piece");
6376 }
6377 else if (auto w = dynamic_cast<SW_TileBlock*>(&widget))
6378 {
6379 list.add_tile(&w->tile, w->w, w->h, "TileBlock");
6380 }
6381 else if (auto w = dynamic_cast<SW_MiniTile*>(&widget))
6382 {
6383 if (w->tile == -1)
6384 return;
6385
6386 list.add_tile(&w->tile, "MiniTile");
6387 }
6388 else if (auto w = dynamic_cast<SW_GaugePiece*>(&widget))
6389 {
6390 int fr = w->frames ? w->frames : 1;
6391 fr = fr * (1+(w->get_per_container()/(w->unit_per_frame+1)));
6392 if(!(w->flags&SUBSCR_GAUGE_FULLTILE))
6393 fr = (fr/4_zf).getCeil();
6394
6395 for(auto q = 0; q < 4; ++q)
6396 {
6397 list.add_tile(&w->mts[q].mt_tile, fr, 1, fmt::format("Gauge Tile {}", q));
6398 }
6399 }
6400 }
6401
6402 static void collect_subscreen_tiles(SubscrPage& page, TileMoveList& list)
6403 {
6404 for(auto q = 0; q < page.contents.size(); ++q)
6405 {
6406 size_t indx = list.move_refs.size();
6407 collect_subscreen_tiles(*page.contents[q], list);
6408 for(; indx < list.move_refs.size(); ++indx)
6409 {
6410 auto& ref = list.move_refs[indx];
6411 ref->name = fmt::format("Widget {} - {}", q, ref->name);
6412 }
6413 }
6414 }
6415
6416 static void collect_subscreen_tiles(ZCSubscreen& subscreen, TileMoveList& list)
6417 {
6418 for (auto q = 0; q < subscreen.pages.size(); ++q)
6419 {
6420 size_t indx = list.move_refs.size();
6421 collect_subscreen_tiles(subscreen.pages[q], list);
6422 for(; indx < list.move_refs.size(); ++indx)
6423 {
6424 auto& ref = list.move_refs[indx];
6425 ref->name = fmt::format("Page {} - {}", q, ref->name);
6426 }
6427 }
6428 }
6429
6430 bool _handle_tile_move(TileMoveProcess dest_process, optional<TileMoveProcess> source_process, int diff, TileMoveUndo* on_undo = nullptr, std::function<void(int32_t)> every_proc = nullptr, TileMoveList::Mode mode = TileMoveList::Mode::MOVE)
6431 {
6432 bool BSZ2 = get_qr(qr_BSZELDA);
6433 bool move = source_process.has_value();
6434 TileMoveUndo local_undo;
6435 TileMoveUndo& storage = on_undo ? *on_undo : local_undo;
6436 auto& vec = storage.vec;
6437 storage.diff = diff;
6438 storage.state = false;
6439
6440 //Combos
6441 {
6442 auto& movelist = vec.emplace_back(std::make_unique<TileMoveList>(
6443 dest_process, source_process, mode,
6444 move
6445 ? "The tiles used by the following combos will be partially cleared by the move."
6446 : "The tiles used by the following combos will be partially or completely overwritten by this process."
6447 ));
6448 for(int32_t q = 0; q < MAXCOMBOS; ++q)
6449 {
6450 auto& cmb = combobuf[q];
6451 auto lbl = fmt::format("Combo {}{}", q, cmb.label.empty() ? ""
6452 : fmt::format(" ({})", cmb.label));
6453 movelist->add_combo(&cmb, lbl);
6454
6455 //type-specific
6456 char const* type_name = ZI.getComboTypeName(cmb.type);
6457 switch(cmb.type)
6458 {
6459 case cSPOTLIGHT:
6460 {
6461 if(!(cmb.usrflags & cflag1))
6462 break;
6463 movelist->add_tile_10k(&cmb.attributes[0], 16, 1, fmt::format("{} - Type '{}' - Beam Tiles", lbl, type_name));
6464 break;
6465 }
6466 }
6467 }
6468 if(!every_proc && !movelist->check_prot())
6469 return false;
6470 }
6471 //Items
6472 {
6473 auto& movelist = vec.emplace_back(std::make_unique<TileMoveList>(
6474 dest_process, source_process, mode,
6475 move
6476 ? "The tiles used by the following items will be partially cleared by the move."
6477 : "The tiles used by the following items will be partially or completely overwritten by this process."
6478 ));
6479 build_bii_list(false);
6480 for(int32_t u=0; u<MAXITEMS; u++)
6481 {
6482 auto id = bii[u].i;
6483 itemdata& itm = itemsbuf[id];
6484 if(itm.family == itype_bottle)
6485 {
6486 vector<std::tuple<int,int,int>> rects;
6487 auto fr = itm.frames;
6488 for(int q = 0; q < NUM_BOTTLE_TYPES; ++q)
6489 {
6490 bottletype const& bt = QMisc.bottle_types[q];
6491 if(bt.is_blank())
6492 continue;
6493 rects.emplace_back(fr+q*fr, fr, 1);
6494 }
6495 movelist->add_tile(&itm.tile, fr, 1, fmt::format("Item {}", id),
6496 false, 0, 0, rects);
6497 }
6498 else movelist->add_tile(&itm.tile, itm.frames, 1, fmt::format("Item {}", id));
6499 }
6500 if(!every_proc && !movelist->check_prot())
6501 return false;
6502 }
6503 //Weapon sprites
6504 {
6505 auto& movelist = vec.emplace_back(std::make_unique<TileMoveList>(
6506 dest_process, source_process, mode,
6507 move
6508 ? "The tiles used by the following weapons will be partially cleared by the move."
6509 : "The tiles used by the following weapons will be partially or completely overwritten by this process."
6510 ));
6511 build_biw_list();
6512
6513 for(int32_t u=0; u<MAXWPNS; u++)
6514 {
6515 bool ignore_frames=false;
6516 int32_t m=0;
6517
6518 auto id = biw[u].i;
6519 auto& wpn = wpnsbuf[id];
6520
6521 switch(biw[u].i)
6522 {
6523 case wSWORD:
6524 case wWSWORD:
6525 case wMSWORD:
6526 case wXSWORD:
6527 m=3+((wpnsbuf[biw[u].i].type==3)?1:0);
6528 break;
6529
6530 case wSWORDSLASH:
6531 case wWSWORDSLASH:
6532 case wMSWORDSLASH:
6533 case wXSWORDSLASH:
6534 m=4;
6535 break;
6536
6537 case iwMMeter:
6538 m=9;
6539 break;
6540
6541 case wBRANG:
6542 case wMBRANG:
6543 case wFBRANG:
6544 m=BSZ2?1:3;
6545 break;
6546
6547 case wBOOM:
6548 case wSBOOM:
6549 case ewBOOM:
6550 case ewSBOOM:
6551 ignore_frames=true;
6552 m=2;
6553 break;
6554
6555 case wWAND:
6556 m=1;
6557 break;
6558
6559 case wMAGIC:
6560 m=1;
6561 break;
6562
6563 case wARROW:
6564 case wSARROW:
6565 case wGARROW:
6566 case ewARROW:
6567 m=1;
6568 break;
6569
6570 case wHAMMER:
6571 m=8;
6572 break;
6573
6574 case wHSHEAD:
6575 m=1;
6576 break;
6577
6578 case wHSCHAIN_H:
6579 m=1;
6580 break;
6581
6582 case wHSCHAIN_V:
6583 m=1;
6584 break;
6585
6586 case wHSHANDLE:
6587 m=1;
6588 break;
6589
6590 case iwDeath:
6591 if(get_qr(qr_HARDCODED_ENEMY_ANIMS))
6592 {
6593 ignore_frames = true;
6594 m=BSZ2?4:2;
6595 }
6596 break;
6597
6598 case iwSpawn:
6599 if(get_qr(qr_HARDCODED_ENEMY_ANIMS))
6600 {
6601 ignore_frames = true;
6602 m=3;
6603 }
6604 break;
6605 }
6606
6607 movelist->add_tile(&wpn.tile, zc_max((ignore_frames?0:wpn.frames),1)+m,
6608 1, fmt::format("{} {}", biw[u].s, id));
6609
6610 //Tile 54+55 are "Impact (not shown in sprite list)", for u==3 "Arrow" and u==9 "Boomerang"
6611 //...these can't be updated by a move.
6612 if((u==3)||(u==9))
6613 {
6614 static int32_t impact_tiles[2] = {54,54};
6615 auto& tile = impact_tiles[u==3 ? 0 : 1];
6616 tile = 54; //dummy tile, ensure it's correct
6617 movelist->add_tile(&tile, 2, 1,
6618 fmt::format("{} Impact (not shown in sprite list)",(u==3)?"Arrow":"Boomerang"),
6619 true);
6620 }
6621 }
6622 if(!every_proc && !movelist->check_prot())
6623 return false;
6624 }
6625 //Player sprites
6626 {
6627 auto& movelist = vec.emplace_back(std::make_unique<TileMoveList>(
6628 dest_process, source_process, mode,
6629 move
6630 ? "The tiles used by the following player sprites will be partially cleared by the move."
6631 : "The tiles used by the following player sprites will be partially or completely overwritten by this process."
6632 ));
6633 {
6634 int32_t a_style=(zinit.heroAnimationStyle);
6635 #define ADD_PLAYER_SPRITE(ref_sprite, frames, name) \
6636 do \
6637 { \
6638 movelist->add_tile(&ref_sprite[spr_tile], \
6639 (ref_sprite[spr_extend] < 2 ? 1 : 2) * frames, \
6640 ref_sprite[spr_extend] < 1 ? 1 : 2, \
6641 name, false, \
6642 ref_sprite[spr_extend] < 2 ? 0 : -1, \
6643 ref_sprite[spr_extend] < 1 ? 0 : -1); \
6644 } while(false)
6645 // + (ref_sprite[spr_extend] < 2 ? 0 : 1) //this was on some of the 'width's before... but doesn't make sense?
6646
6647 for(int32_t i=0; i<4; ++i)
6648 {
6649 ADD_PLAYER_SPRITE(walkspr[i], quick_select_3(a_style, (i==0?1:2), 3, 9), fmt::format("Walking ({})", dirstr_proper[i]));
6650 }
6651
6652 for(int32_t i=0; i<4; ++i)
6653 {
6654 ADD_PLAYER_SPRITE(slashspr[i], quick_select_3(a_style, 1, 1, 6), fmt::format("Slashing ({})", dirstr_proper[i]));
6655 }
6656
6657 for(int32_t i=0; i<4; ++i)
6658 {
6659 ADD_PLAYER_SPRITE(stabspr[i], quick_select_3(a_style, 1, 1, 3), fmt::format("Stabbing ({})", dirstr_proper[i]));
6660 }
6661
6662 for(int32_t i=0; i<4; ++i)
6663 {
6664 ADD_PLAYER_SPRITE(poundspr[i], quick_select_3(a_style, 1, 1, 3), fmt::format("Pounding ({})", dirstr_proper[i]));
6665 }
6666
6667 for(int32_t i=0; i<2; ++i)
6668 {
6669 ADD_PLAYER_SPRITE(holdspr[0][i], 1, fmt::format("Hold (Land, {}-hand)", i+1));
6670 }
6671
6672 ADD_PLAYER_SPRITE(castingspr, 1, "Casting");
6673
6674 for(int32_t i=0; i<4; ++i)
6675 {
6676 ADD_PLAYER_SPRITE(floatspr[i], quick_select_3(a_style, 2, 3, 4), fmt::format("Floating ({})", dirstr_proper[i]));
6677 }
6678
6679 for(int32_t i=0; i<4; ++i)
6680 {
6681 ADD_PLAYER_SPRITE(swimspr[i], quick_select_3(a_style, 2, 3, 4), fmt::format("Swimming ({})", dirstr_proper[i]));
6682 }
6683
6684 for(int32_t i=0; i<4; ++i)
6685 {
6686 ADD_PLAYER_SPRITE(divespr[i], quick_select_3(a_style, 2, 3, 4), fmt::format("Diving ({})", dirstr_proper[i]));
6687 }
6688
6689 for(int32_t i=0; i<2; ++i)
6690 {
6691 ADD_PLAYER_SPRITE(holdspr[1][i], 1, fmt::format("Hold (Water, {}-hand)", i));
6692 }
6693
6694 for(int32_t i=0; i<4; ++i)
6695 {
6696 ADD_PLAYER_SPRITE(jumpspr[i], 3, fmt::format("Jumping ({})", dirstr_proper[i]));
6697 }
6698
6699 for(int32_t i=0; i<4; ++i)
6700 {
6701 ADD_PLAYER_SPRITE(chargespr[i], quick_select_3(a_style, 2, 3, 9), fmt::format("Charging ({})", dirstr_proper[i]));
6702 }
6703 for(int32_t i=0; i<4; ++i)
6704 {
6705 ADD_PLAYER_SPRITE(revslashspr[i], quick_select_3(a_style, 1, 1, 6), fmt::format("Slash 2 ({})", dirstr_proper[i]));
6706 }
6707 for(int32_t i=0; i<4; ++i)
6708 {
6709 ADD_PLAYER_SPRITE(fallingspr[i], 7, fmt::format("Falling ({})", dirstr_proper[i]));
6710 }
6711 for(int32_t i=0; i<4; ++i)
6712 {
6713 ADD_PLAYER_SPRITE(liftingspr[i], liftingspr[i][spr_frames], fmt::format("Lifting ({})", dirstr_proper[i]));
6714 }
6715 for(int32_t i=0; i<4; ++i)
6716 {
6717 ADD_PLAYER_SPRITE(liftingwalkspr[i], quick_select_3(a_style, (i==0?1:2), 3, 9), fmt::format("Lift-Walking ({})", dirstr_proper[i]));
6718 }
6719 for(int32_t i=0; i<4; ++i)
6720 {
6721 ADD_PLAYER_SPRITE(drowningspr[i], quick_select_3(a_style, 2, 3, 3), fmt::format("Drowning ({})", dirstr_proper[i]));
6722 }
6723 for(int32_t i=0; i<4; ++i)
6724 {
6725 ADD_PLAYER_SPRITE(drowning_lavaspr[i], quick_select_3(a_style, 2, 3, 3), fmt::format("Lava Drowning ({})", dirstr_proper[i]));
6726 }
6727 for(int32_t i=0; i<4; ++i)
6728 {
6729 ADD_PLAYER_SPRITE(sideswimspr[i], quick_select_3(a_style, 2, 3, 3), fmt::format("Side-Swimming ({})", dirstr_proper[i]));
6730 }
6731 //69
6732 for(int32_t i=0; i<4; ++i)
6733 {
6734 ADD_PLAYER_SPRITE(sideswimslashspr[i], quick_select_3(a_style, 1, 1, 6), fmt::format("Side-Swim Slash ({})", dirstr_proper[i]));
6735 }
6736 //73
6737 for(int32_t i=0; i<4; ++i)
6738 {
6739 ADD_PLAYER_SPRITE(sideswimstabspr[i], quick_select_3(a_style, 1, 1, 3), fmt::format("Side-Swim Stab ({})", dirstr_proper[i]));
6740 }
6741 //77
6742 for(int32_t i=0; i<4; ++i)
6743 {
6744 ADD_PLAYER_SPRITE(sideswimpoundspr[i], quick_select_3(a_style, 1, 1, 3), fmt::format("Side-Swim Pound ({})", dirstr_proper[i]));
6745 }
6746 //81
6747 for(int32_t i=0; i<4; ++i)
6748 {
6749 ADD_PLAYER_SPRITE(sideswimchargespr[i], quick_select_3(a_style, 2, 3, 9), fmt::format("Side-Swim Charging ({})", dirstr_proper[i]));
6750 }
6751 //85
6752 ADD_PLAYER_SPRITE(sideswimholdspr[spr_hold1], 1, "Hold (Side-Water, 1-hand)");
6753 ADD_PLAYER_SPRITE(sideswimholdspr[spr_hold2], 1, "Hold (Side-Water, 2-hand)");
6754 ADD_PLAYER_SPRITE(sideswimcastingspr, 1, "Side-Swim Casting");
6755 for(int32_t i=0; i<4; ++i)
6756 {
6757 ADD_PLAYER_SPRITE(sidedrowningspr[i], quick_select_3(a_style, 2, 3, 3), fmt::format("Side-Swim Drowning ({})", dirstr_proper[i]));
6758 }
6759 //91
6760 }
6761 if(!every_proc && !movelist->check_prot())
6762 return false;
6763 }
6764 //Map Styles
6765 {
6766 auto& movelist = vec.emplace_back(std::make_unique<TileMoveList>(
6767 dest_process, source_process, mode,
6768 move
6769 ? "The tiles used by the following map styles will be partially cleared by the move."
6770 : "The tiles used by the following map styles will be partially or completely overwritten by this process."
6771 ));
6772 movelist->add_tile(&QMisc.colors.blueframe_tile, 2, 2, "Frame");
6773 movelist->add_tile(&QMisc.colors.HCpieces_tile, zinit.hcp_per_hc, 1, "Heart Container Piece");
6774 movelist->add_tile(&QMisc.colors.triforce_tile, BSZ2?2:1, BSZ2?3:1, "McGuffin Fragment");
6775 movelist->add_tile(&QMisc.colors.triframe_tile, BSZ2?7:6, BSZ2?7:3, "McGuffin Frame");
6776 movelist->add_tile(&QMisc.colors.overworld_map_tile, 5, 3, "Overworld Map");
6777 movelist->add_tile(&QMisc.colors.dungeon_map_tile, 5, 3, "Dungeon Map");
6778 if(!every_proc && !movelist->check_prot())
6779 return false;
6780 }
6781 //Game Icons
6782 {
6783 auto& movelist = vec.emplace_back(std::make_unique<TileMoveList>(
6784 dest_process, source_process, mode,
6785 move
6786 ? "The tiles used by the following game icons will be partially cleared by the move."
6787 : "The tiles used by the following game icons will be partially or completely overwritten by this process."
6788 ));
6789 for(int32_t u=0; u<4; u++)
6790 movelist->add_tile(&QMisc.icons[u], fmt::format("Game Icon {}", u));
6791 if(!every_proc && !movelist->check_prot())
6792 return false;
6793 }
6794 //DMaps
6795 {
6796 auto& movelist = vec.emplace_back(std::make_unique<TileMoveList>(
6797 dest_process, source_process, mode,
6798 move
6799 ? "The tiles used by the following dmaps will be partially cleared by the move."
6800 : "The tiles used by the following dmaps will be partially or completely overwritten by this process."
6801 ));
6802 for(int32_t u=0; u<MAXDMAPS; u++)
6803 {
6804 auto& dm = DMaps[u];
6805 movelist->add_tile(&dm.minimap_1_tile, 5, 3, fmt::format("DMap {} - Minimap (Empty)", u));
6806 movelist->add_tile(&dm.minimap_2_tile, 5, 3, fmt::format("DMap {} - Minimap (Filled)", u));
6807 movelist->add_tile(&dm.largemap_1_tile, BSZ2?7:9, 5, fmt::format("DMap {} - Large Map (Empty)", u));
6808 movelist->add_tile(&dm.largemap_2_tile, BSZ2?7:9, 5, fmt::format("DMap {} - Large Map (Filled)", u));
6809 }
6810 if(!every_proc && !movelist->check_prot())
6811 return false;
6812 }
6813 //Enemies
6814 {
6815 auto& movelist = vec.emplace_back(std::make_unique<TileMoveList>(
6816 dest_process, source_process, mode,
6817 move
6818 ? "The tiles used by the following enemies will be partially cleared by the move."
6819 : "The tiles used by the following enemies will be partially or completely overwritten by this process."
6820 ));
6821 build_bie_list(false);
6822 bool newtiles=get_qr(qr_NEWENEMYTILES)!=0;
6823 for(int u=0; u<eMAXGUYS; u++)
6824 {
6825 guydata& enemy=guysbuf[bie[u].i];
6826 bool darknut=false;
6827 int32_t gleeok=0;
6828
6829 if(enemy.family==eeWALK && ((enemy.flags&(guy_shield_back|guy_shield_front|guy_shield_left|guy_shield_right))!=0))
6830 darknut=true;
6831 else if(enemy.family==eeGLEEOK)
6832 {
6833 // Not certain this is the right thing to check...
6834 if(enemy.attributes[2] == 0)
6835 gleeok=1;
6836 else
6837 gleeok=2;
6838 }
6839
6840 // Dummied out enemies
6841 if(bie[u].i>=eOCTO1S && bie[u].i<e177)
6842 {
6843 if(old_guy_string[bie[u].i][strlen(old_guy_string[bie[u].i])-1]==' ')
6844 {
6845 continue;
6846 }
6847 }
6848
6849 if(newtiles)
6850 {
6851 if(guysbuf[bie[u].i].e_tile==0)
6852 {
6853 continue;
6854 }
6855
6856 vector<std::tuple<int,int,int>> rects;
6857
6858 if(darknut)
6859 {
6860 rects.emplace_back(enemy.e_tile+6*TILES_PER_ROW, enemy.e_width, enemy.e_height);
6861 }
6862 else if(enemy.family==eeGANON)
6863 {
6864 rects.emplace_back(enemy.e_tile+2*TILES_PER_ROW, 20, 4);
6865 }
6866 else if(gleeok) //No idea if this is actually *RIGHT*, but I copied what was here before faithfully -Em
6867 {
6868 for(int32_t j=0; j<4; ++j)
6869 {
6870 rects.emplace_back(
6871 TILECOL(guysbuf[bie[u].i].e_tile+(gleeok>1?-4:8)) + TILES_PER_ROW*TILEROW(guysbuf[bie[u].i].e_tile+8)+(j<<1)+(gleeok>1?1:0),
6872 4, 1);
6873 }
6874 int32_t c=TILECOL(guysbuf[bie[u].i].e_tile)+(gleeok>1?-12:0);
6875 int32_t r=TILEROW(guysbuf[bie[u].i].e_tile)+(gleeok>1?17:8);
6876 rects.emplace_back(c+TILES_PER_ROW*r, 20, 3);
6877 rects.emplace_back(c+TILES_PER_ROW*(r+3), 16, 6);
6878 }
6879 movelist->add_tile(&enemy.e_tile, enemy.e_width, enemy.e_height, fmt::format("Enemy {} ({}) 'New'", u, bie[u].s),
6880 false, 0, 0, rects);
6881 }
6882 else
6883 {
6884 if(guysbuf[bie[u].i].tile==0)
6885 {
6886 continue;
6887 }
6888 movelist->add_tile(&enemy.tile, enemy.width, enemy.height, fmt::format("Enemy {} ({}) 'Old'", u, bie[u].s));
6889
6890 if(guysbuf[bie[u].i].s_tile!=0)
6891 {
6892 movelist->add_tile(&enemy.s_tile, enemy.s_width, enemy.s_height, fmt::format("Enemy {} ({}) 'Special'", u, bie[u].s));
6893 }
6894 }
6895 }
6896 if(!every_proc && !movelist->check_prot())
6897 return false;
6898 }
6899 //Subscreens
6900 {
6901 auto& movelist = vec.emplace_back(std::make_unique<TileMoveList>(
6902 dest_process, source_process, mode,
6903 move
6904 ? "The tiles used by the following subscreen widgets will be partially cleared by the move."
6905 : "The tiles used by the following subscreen widgets will be partially or completely overwritten by this process."
6906 ));
6907
6908 for(auto q = 0; q < subscreens_active.size(); ++q)
6909 {
6910 size_t indx = movelist->move_refs.size();
6911 collect_subscreen_tiles(subscreens_active[q], *movelist.get());
6912 for(; indx < movelist->move_refs.size(); ++indx)
6913 {
6914 auto& ref = movelist->move_refs[indx];
6915 ref->name = fmt::format("Active Subscr {} - {}", q, ref->name);
6916 }
6917 }
6918 for(auto q = 0; q < subscreens_passive.size(); ++q)
6919 {
6920 size_t indx = movelist->move_refs.size();
6921 collect_subscreen_tiles(subscreens_passive[q], *movelist.get());
6922 for(; indx < movelist->move_refs.size(); ++indx)
6923 {
6924 auto& ref = movelist->move_refs[indx];
6925 ref->name = fmt::format("Passive Subscr {} - {}", q, ref->name);
6926 }
6927 }
6928 for(auto q = 0; q < subscreens_overlay.size(); ++q)
6929 {
6930 size_t indx = movelist->move_refs.size();
6931 collect_subscreen_tiles(subscreens_overlay[q], *movelist.get());
6932 for(; indx < movelist->move_refs.size(); ++indx)
6933 {
6934 auto& ref = movelist->move_refs[indx];
6935 ref->name = fmt::format("Overlay Subscr {} - {}", q, ref->name);
6936 }
6937 }
6938 if(!every_proc && !movelist->check_prot())
6939 return false;
6940 }
6941 //Strings
6942 {
6943 auto& movelist = vec.emplace_back(std::make_unique<TileMoveList>(
6944 dest_process, source_process, mode,
6945 move
6946 ? "The tiles used by the following strings will be partially cleared by the move."
6947 : "The tiles used by the following strings will be partially or completely overwritten by this process."
6948 ));
6949 for(size_t q = 0; q < msg_count; ++q)
6950 {
6951 MsgStr& str = MsgStrings[q];
6952 bool fulltile = str.stringflags & STRINGFLAG_FULLTILE;
6953 movelist->add_tile(&str.tile, fulltile ? (str.w/16_zf).getCeil() : 2,
6954 fulltile ? (str.h/16_zf).getCeil() : 2, fmt::format("{} (BG): '{}'", q, util::snip(str.s,100)));
6955 movelist->add_tile(&str.portrait_tile, str.portrait_tw, str.portrait_th,
6956 fmt::format("{} (Port.): '{}'", q, util::snip(str.s,100)));
6957 }
6958 if(!every_proc && !movelist->check_prot())
6959 return false;
6960 }
6961
6962 if(source_process) //Apply the 'diff' value to all moved tiles
6963 storage.redo();
6964 if(every_proc)
6965 for(auto &list : vec)
6966 for(auto &ref : list->move_refs)
6967 ref->forEach(every_proc);
6968 return true;
6969 }
6970 bool handle_tile_move(TileMoveProcess dest_process)
6971 {
6972 return _handle_tile_move(dest_process, nullopt, 0);
6973 }
6974 bool handle_tile_move(TileMoveProcess dest_process, TileMoveProcess source_process, int diff, TileMoveUndo& on_undo)
6975 {
6976 return _handle_tile_move(dest_process, source_process, diff, &on_undo);
6977 }
6978 void for_every_used_tile(std::function<void(int32_t)> proc)
6979 {
6980 reset_combo_animations();
6981 reset_combo_animations2();
6982 TileMoveProcess all_tiles {.rect = false, ._first = 0, ._last = NEWMAXTILES-1};
6983 _handle_tile_move(all_tiles, nullopt, 0, nullptr, proc, TileMoveList::Mode::CHECK_ALL);
6984 }
6985
6986 bool _handle_combo_move(ComboMoveProcess dest_process, optional<ComboMoveProcess> source_process, int diff, ComboMoveUndo* on_undo)
6987 {
6988 bool BSZ2 = get_qr(qr_BSZELDA);
6989 bool move = source_process.has_value();
6990 ComboMoveUndo local_undo;
6991 ComboMoveUndo& storage = on_undo ? *on_undo : local_undo;
6992 auto& vec = storage.vec;
6993 auto& combo_links = storage.combo_links;
6994 storage.diff = diff;
6995 storage.state = false;
6996 //Combo relative links
6997 {
6998 for(int32_t q = 0; q < MAXCOMBOS; ++q)
6999 {
7000 newcombo& cmb = combobuf[q];
7001 if(cmb.trigchange)
7002 combo_links.add_to(q, q+cmb.trigchange);
7003 bool next = cmb.flag == mfSECRETSNEXT;
7004 switch(cmb.type)
7005 {
7006 case cPOUND:
7007 case cLOCKBLOCK: case cLOCKBLOCK2:
7008 case cBOSSLOCKBLOCK: case cBOSSLOCKBLOCK2:
7009 case cCHEST: case cCHEST2:
7010 case cLOCKEDCHEST: case cLOCKEDCHEST2:
7011 case cBOSSCHEST: case cBOSSCHEST2:
7012 case cSTEP: case cSTEPSAME: case cSTEPALL: case cSTEPCOPY:
7013 case cSLASHNEXT: case cSLASHNEXTITEM: case cBUSHNEXT:
7014 case cSLASHNEXTTOUCHY: case cSLASHNEXTITEMTOUCHY: case cBUSHNEXTTOUCHY:
7015 case cTALLGRASSNEXT: case cCRUMBLE:
7016 next = true;
7017 break;
7018 case cCSWITCH: case cCSWITCHBLOCK:
7019 combo_links.add_to(q, q+cmb.attributes[0]);
7020 break;
7021 case cLIGHTTARGET:
7022 if(cmb.usrflags & cflag1)
7023 combo_links.add_to(q, q-1);
7024 else next = true;
7025 break;
7026 case cSTEPSFX:
7027 if((cmb.usrflags&(cflag1|cflag3)) == cflag1)
7028 next = true;
7029 break;
7030 }
7031 if(next)
7032 combo_links.add_to(q, q+1);
7033 }
7034 }
7035
7036 //This function is expensive! Any optimizations possible should be made. -Em
7037
7038 //OPT: Check for a 0-val preemptively, to avoid processing the fmt::format strings
7039 #define ADDC(ptr, str) \
7040 if(*ptr) movelist->add_combo(ptr, ComboProtection ? str : "");
7041 #define ADDC_10k(ptr, str) \
7042 if(*ptr) movelist->add_combo_10k(ptr, ComboProtection ? str : "");
7043 //Combos
7044 {
7045 auto& movelist = vec.emplace_back(std::make_unique<ComboMoveList>(
7046 combo_links, dest_process, source_process,
7047 move
7048 ? "The combos used by the following combos will be partially cleared by the move."
7049 : "The combos used by the following combos will be partially or completely overwritten by this process."
7050 ));
7051 for(int32_t q = 0; q < MAXCOMBOS; ++q)
7052 {
7053 newcombo& cmb = combobuf[q];
7054 auto lbl = fmt::format("{}{}", q, cmb.label.empty() ? ""
7055 : fmt::format(" ({})", cmb.label));
7056 ADDC(&cmb.nextcombo, fmt::format("{} - Combo Cycle", lbl));
7057 ADDC(&cmb.liftcmb, fmt::format("{} - Lift Combo", lbl));
7058 ADDC(&cmb.liftundercmb, fmt::format("{} - Lift Undercombo", lbl));
7059 ADDC(&cmb.prompt_cid, fmt::format("{} - Triggers ButtonPrompt", lbl));
7060
7061 //type-specific
7062 char const* type_name = ZI.getComboTypeName(cmb.type);
7063 switch(cmb.type)
7064 {
7065 case cLOCKEDCHEST: case cBOSSCHEST:
7066 if(cmb.usrflags & cflag13)
7067 ADDC_10k(&cmb.attributes[2], fmt::format("{} - Type '{}' - Locked Prompt", lbl, type_name));
7068 [[fallthrough]];
7069 case cCHEST:
7070 if(cmb.usrflags & cflag13)
7071 ADDC_10k(&cmb.attributes[1], fmt::format("{} - Type '{}' - Prompt", lbl, type_name));
7072 break;
7073 case cLOCKBLOCK: case cBOSSLOCKBLOCK:
7074 if(cmb.usrflags & cflag13)
7075 {
7076 ADDC_10k(&cmb.attributes[1], fmt::format("{} - Type '{}' - Prompt", lbl, type_name));
7077 ADDC_10k(&cmb.attributes[2], fmt::format("{} - Type '{}' - Locked Prompt", lbl, type_name));
7078 }
7079 break;
7080 case cSIGNPOST:
7081 if(cmb.usrflags & cflag13)
7082 ADDC_10k(&cmb.attributes[1], fmt::format("{} - Type '{}' - Prompt", lbl, type_name));
7083 break;
7084 case cBUTTONPROMPT:
7085 if(cmb.usrflags & cflag13)
7086 ADDC_10k(&cmb.attributes[0], fmt::format("{} - Type '{}' - Prompt", lbl, type_name));
7087 break;
7088 }
7089 }
7090
7091 if(!movelist->check_prot())
7092 return false;
7093 }
7094 //Door Combo Sets
7095 {
7096 auto& movelist = vec.emplace_back(std::make_unique<ComboMoveList>(
7097 combo_links, dest_process, source_process,
7098 move
7099 ? "The combos used by the following screens will be partially cleared by the move."
7100 : "The combos used by the following screens will be partially or completely overwritten by this process."
7101 ));
7102 static const char* door_names[9] = {
7103 "Wall", "Locked", "Shuttered", "Boss", "Bombed", "Open", "Unlocked", "Open Shuttered", "Open Boss"
7104 };
7105 for(int32_t i=0; i<MAXDOORCOMBOSETS; i++)
7106 {
7107 auto& dcs = DoorComboSets[i];
7108 for(int32_t j=0; j<9; j++)
7109 {
7110 if(j<4)
7111 {
7112 ADDC(&dcs.walkthroughcombo[j], fmt::format("{} ({}): Walk-Through {}", i, dcs.name, j));
7113
7114 if(j<3)
7115 {
7116 if(j<2)
7117 {
7118 ADDC(&dcs.bombdoorcombo_u[j], fmt::format("{} ({}): Unused? bombdoorcombo_u {}", i, dcs.name, j));
7119 ADDC(&dcs.bombdoorcombo_d[j], fmt::format("{} ({}): Unused? bombdoorcombo_d {}", i, dcs.name, j));
7120 }
7121 ADDC(&dcs.bombdoorcombo_l[j], fmt::format("{} ({}): Unused? bombdoorcombo_l {}", i, dcs.name, j));
7122 ADDC(&dcs.bombdoorcombo_r[j], fmt::format("{} ({}): Unused? bombdoorcombo_r {}", i, dcs.name, j));
7123 }
7124 }
7125
7126 for(int32_t k=0; k<6; k++)
7127 {
7128 if(k<4)
7129 {
7130 ADDC(&dcs.doorcombo_u[j][k], fmt::format("{} ({}): Top, {} #{}", i, dcs.name, door_names[j], k));
7131 ADDC(&dcs.doorcombo_d[j][k], fmt::format("{} ({}): Bottom, {} #{}", i, dcs.name, door_names[j], k));
7132 }
7133
7134 ADDC(&dcs.doorcombo_l[j][k], fmt::format("{} ({}): Left, {} #{}", i, dcs.name, door_names[j], k));
7135 ADDC(&dcs.doorcombo_r[j][k], fmt::format("{} ({}): Right, {} #{}", i, dcs.name, door_names[j], k));
7136 }
7137 }
7138 }
7139
7140 if(!movelist->check_prot())
7141 return false;
7142 }
7143 //Combo Pools
7144 {
7145 auto& movelist = vec.emplace_back(std::make_unique<ComboMoveList>(
7146 combo_links, dest_process, source_process,
7147 move
7148 ? "The combos used by the following combo pools will be partially cleared by the move."
7149 : "The combos used by the following combo pools will be partially or completely overwritten by this process."
7150 ));
7151 for(auto q = 0; q < MAXCOMBOPOOLS; ++q)
7152 {
7153 combo_pool& pool = combo_pools[q];
7154 int idx = 0;
7155 for(cpool_entry& cp : pool.combos)
7156 ADDC(&cp.cid, fmt::format("{} index {}", q, idx++));
7157 }
7158
7159 if(!movelist->check_prot())
7160 return false;
7161 }
7162 //Auto Combos
7163 {
7164 auto& movelist = vec.emplace_back(std::make_unique<ComboMoveList>(
7165 combo_links, dest_process, source_process,
7166 move
7167 ? "The combos used by the following autocombos will be partially cleared by the move."
7168 : "The combos used by the following autocombos will be partially or completely overwritten by this process."
7169 ));
7170 for (auto q = 0; q < MAXAUTOCOMBOS; ++q)
7171 {
7172 combo_auto& cauto = combo_autos[q];
7173 int idx = 0;
7174 for (autocombo_entry& ac : cauto.combos)
7175 ADDC(&ac.cid, fmt::format("{} index {}", q, idx++));
7176 ADDC(&cauto.cid_erase, fmt::format("{} Erase Combo", q));
7177 ADDC(&cauto.cid_display, fmt::format("{} Display Combo", q));
7178 }
7179
7180 if(!movelist->check_prot())
7181 return false;
7182 }
7183 //Combo Aliases
7184 {
7185 auto& movelist = vec.emplace_back(std::make_unique<ComboMoveList>(
7186 combo_links, dest_process, source_process,
7187 move
7188 ? "The combos used by the following aliases will be partially cleared by the move."
7189 : "The combos used by the following aliases will be partially or completely overwritten by this process."
7190 ));
7191 for(int32_t i=0; i<MAXCOMBOALIASES; i++)
7192 {
7193 //dimensions are 1 less than you would expect -DD
7194 int32_t count=(comboa_lmasktotal(combo_aliases[i].layermask)+1)*(combo_aliases[i].width+1)*(combo_aliases[i].height+1);
7195
7196 for(int32_t j=0; j<count; j++)
7197 {
7198 ADDC(&combo_aliases[i].combos[j], fmt::format("{} index {}", i, j));
7199 }
7200 }
7201
7202 if(!movelist->check_prot())
7203 return false;
7204 }
7205 //Favorite Combos
7206 {
7207 auto& movelist = vec.emplace_back(std::make_unique<ComboMoveList>(
7208 combo_links, dest_process, source_process,
7209 move
7210 ? "The combos used by the following favorite combos will be partially cleared by the move."
7211 : "The combos used by the following favorite combos will be partially or completely overwritten by this process."
7212 ));
7213 for(int32_t i=0; i<MAXFAVORITECOMBOS; i++)
7214 {
7215 if(favorite_combo_modes[i] != dm_normal) //don't hit pools/aliases/autos, only combos!
7216 continue;
7217 ADDC(&favorite_combos[i], fmt::format("Favorite {}", i));
7218 }
7219
7220 if(!movelist->check_prot())
7221 return false;
7222 }
7223 //Bottle Shops
7224 {
7225 auto& movelist = vec.emplace_back(std::make_unique<ComboMoveList>(
7226 combo_links, dest_process, source_process,
7227 move
7228 ? "The combos used by the following bottle shops will be partially cleared by the move."
7229 : "The combos used by the following bottle shops will be partially or completely overwritten by this process."
7230 ));
7231 for(auto q = 0; q < 256; ++q)
7232 for(auto p = 0; p < 3; ++p)
7233 ADDC(&QMisc.bottle_shop_types[q].comb[p], fmt::format("{} slot {}", q, p));
7234
7235 if(!movelist->check_prot())
7236 return false;
7237 }
7238 //Screens //EXPENSIVE! DO THIS LAST!
7239 {
7240 auto& movelist = vec.emplace_back(std::make_unique<ComboMoveList>(
7241 combo_links, dest_process, source_process,
7242 move
7243 ? "The combos used by the following screens will be partially cleared by the move."
7244 : "The combos used by the following screens will be partially or completely overwritten by this process."
7245 ));
7246
7247 for(int32_t i=0; i<map_count && i<MAXMAPS; i++)
7248 {
7249 for(int32_t j=0; j<MAPSCRS; j++)
7250 {
7251 mapscr& scr = TheMaps[i*MAPSCRS+j];
7252
7253 if(!(scr.valid&mVALID))
7254 continue;
7255
7256 ADDC(&scr.undercombo, fmt::format("{}x{:02X} - UnderCombo", i, j));
7257
7258 // Specifying the exact position is too expensive - too much string creation.
7259 std::string data_str = ComboProtection ? fmt::format("{}x{:02X} - Combo", i, j) : "";
7260 for(int32_t k=0; k<176; k++)
7261 ADDC(&scr.data[k], data_str);
7262
7263 for(int32_t k=0; k<128; k++)
7264 ADDC(&scr.secretcombo[k], fmt::format("{}x{:02X} - SecretCombo {}", i, j, k));
7265
7266 word maxffc = scr.numFFC();
7267 for(word k=0; k<maxffc; k++)
7268 {
7269 ffcdata& ffc = scr.ffcs[k];
7270 ADDC(&ffc.data, fmt::format("{}x{:02X} - FFC {}", i, j, k+1));
7271 }
7272 }
7273 }
7274
7275 if(!movelist->check_prot())
7276 return false;
7277 }
7278 if(source_process) //Apply the 'diff' value to all moved combos
7279 storage.redo();
7280 return true;
7281 }
7282
7283 bool handle_combo_move(ComboMoveProcess dest_process)
7284 {
7285 return _handle_combo_move(dest_process, nullopt, 0, nullptr);
7286 }
7287 bool handle_combo_move(ComboMoveProcess dest_process, ComboMoveProcess source_process, int diff, ComboMoveUndo& on_undo)
7288 {
7289 return _handle_combo_move(dest_process, source_process, diff, &on_undo);
7290 }
7291 void register_used_tiles()
7292 {
7293 memset(used_tile_table, 0, sizeof(used_tile_table));
7294 for_every_used_tile([&](int tile)
7295 {
7296 used_tile_table[tile] = true;
7297 });
7298 }
7299
7300 bool overlay_tiles(int32_t &tile,int32_t &tile2,int32_t &copy,int32_t &copycnt, bool rect_sel, bool move, int32_t cs, bool backwards)
7301 {
7302 bool ctrl=(CHECK_CTRL_CMD);
7303 bool copied=false;
7304 copied=overlay_tiles_united(tile,tile2,copy,copycnt,rect_sel,move,cs,backwards);
7305
7306 if(copied)
7307 {
7308 saved=false;
7309 }
7310
7311 return copied;
7312 }
7313
7314 bool overlay_tiles_united(int32_t &tile,int32_t &tile2,int32_t &copy,int32_t &copycnt, bool rect, bool move, int32_t cs, bool backwards)
7315 {
7316 bool alt=(key[KEY_ALT]||key[KEY_ALTGR]);
7317 bool shift=(key[KEY_LSHIFT] || key[KEY_RSHIFT]);
7318
7319 // if tile>tile2 then swap them
7320 if(tile>tile2)
7321 {
7322 zc_swap(tile, tile2);
7323 }
7324
7325 // alt=copy from right
7326 // shift=copy from bottom
7327
7328 int32_t copies=copycnt;
7329 int32_t dest_first=tile;
7330 int32_t dest_last=tile2;
7331 int32_t src_first=copy;
7332 int32_t src_last=copy+copies-1;
7333
7334 int32_t dest_top=0;
7335 int32_t dest_bottom=0;
7336 int32_t src_top=0;
7337 int32_t src_bottom=0;
7338 int32_t src_left=0, src_right=0;
7339 int32_t src_width=0, src_height=0;
7340 int32_t dest_left=0, dest_right=0;
7341 int32_t dest_width=0, dest_height=0;
7342 int32_t rows=0, cols=0;
7343
7344 if(rect)
7345 {
7346 dest_top=TILEROW(dest_first);
7347 dest_bottom=TILEROW(dest_last);
7348 src_top=TILEROW(src_first);
7349 src_bottom=TILEROW(src_last);
7350
7351 src_left= zc_min(TILECOL(src_first),TILECOL(src_last));
7352 src_right=zc_max(TILECOL(src_first),TILECOL(src_last));
7353 src_first=(src_top * TILES_PER_ROW)+src_left;
7354 src_last= (src_bottom*TILES_PER_ROW)+src_right;
7355
7356 dest_left= zc_min(TILECOL(dest_first),TILECOL(dest_last));
7357 dest_right=zc_max(TILECOL(dest_first),TILECOL(dest_last));
7358 dest_first=(dest_top * TILES_PER_ROW)+dest_left;
7359 dest_last= (dest_bottom*TILES_PER_ROW)+dest_right;
7360
7361 //if no dest range set, then set one
7362 if((dest_first==dest_last)&&(src_first!=src_last))
7363 {
7364 if(alt)
7365 {
7366 dest_left=dest_right-(src_right-src_left);
7367 }
7368 else
7369 {
7370 dest_right=dest_left+(src_right-src_left);
7371 }
7372
7373 if(shift)
7374 {
7375 dest_top=dest_bottom-(src_bottom-src_top);
7376 }
7377 else
7378 {
7379 dest_bottom=dest_top+(src_bottom-src_top);
7380 }
7381
7382 dest_first=(dest_top * TILES_PER_ROW)+dest_left;
7383 dest_last= (dest_bottom*TILES_PER_ROW)+dest_right;
7384 }
7385 else
7386 {
7387 if(dest_right-dest_left<src_right-src_left) //destination is shorter than source
7388 {
7389 if(alt) //copy from right tile instead of left
7390 {
7391 src_left=src_right-(dest_right-dest_left);
7392 }
7393 else //copy from left tile
7394 {
7395 src_right=src_left+(dest_right-dest_left);
7396 }
7397 }
7398 else if(dest_right-dest_left>src_right-src_left) //destination is longer than source
7399 {
7400 if(alt) //copy from right tile instead of left
7401 {
7402 dest_left=dest_right-(src_right-src_left);
7403 }
7404 else //copy from left tile
7405 {
7406 dest_right=dest_left+(src_right-src_left);
7407 }
7408 }
7409
7410 if(dest_bottom-dest_top<src_bottom-src_top) //destination is shorter than source
7411 {
7412 if(shift) //copy from bottom tile instead of top
7413 {
7414 src_top=src_bottom-(dest_bottom-dest_top);
7415 }
7416 else //copy from top tile
7417 {
7418 src_bottom=src_top+(dest_bottom-dest_top);
7419 }
7420 }
7421 else if(dest_bottom-dest_top>src_bottom-src_top) //destination is longer than source
7422 {
7423 if(shift) //copy from bottom tile instead of top
7424 {
7425 dest_top=dest_bottom-(src_bottom-src_top);
7426 }
7427 else //copy from top tile
7428 {
7429 dest_bottom=dest_top+(src_bottom-src_top);
7430 }
7431 }
7432
7433 src_first=(src_top * TILES_PER_ROW)+src_left;
7434 src_last= (src_bottom*TILES_PER_ROW)+src_right;
7435 dest_first=(dest_top * TILES_PER_ROW)+dest_left;
7436 dest_last= (dest_bottom*TILES_PER_ROW)+dest_right;
7437 }
7438
7439 cols=src_right-src_left+1;
7440 rows=src_bottom-src_top+1;
7441
7442 dest_width=dest_right-dest_left+1;
7443 dest_height=dest_bottom-dest_top+1;
7444 src_width=src_right-src_left+1;
7445 src_height=src_bottom-src_top+1;
7446
7447 }
7448 else //!rect
7449 {
7450 //if no dest range set, then set one
7451 if((dest_first==dest_last)&&(src_first!=src_last))
7452 {
7453 if(alt)
7454 {
7455 dest_first=dest_last-(src_last-src_first);
7456 }
7457 else
7458 {
7459 dest_last=dest_first+(src_last-src_first);
7460 }
7461 }
7462 else
7463 {
7464 if(dest_last-dest_first<src_last-src_first) //destination is shorter than source
7465 {
7466 if(alt) //copy from last tile instead of first
7467 {
7468 src_first=src_last-(dest_last-dest_first);
7469 }
7470 else //copy from first tile
7471 {
7472 src_last=src_first+(dest_last-dest_first);
7473 }
7474 }
7475 else if(dest_last-dest_first>src_last-src_first) //destination is longer than source
7476 {
7477 if(alt) //copy from last tile instead of first
7478 {
7479 dest_first=dest_last-(src_last-src_first);
7480 }
7481 else //copy from first tile
7482 {
7483 dest_last=dest_first+(src_last-src_first);
7484 }
7485 }
7486 }
7487
7488 copies=dest_last-dest_first+1;
7489 }
7490
7491
7492
7493 char buf2[80], buf3[80], buf4[80];
7494 sprintf(buf2, " ");
7495 sprintf(buf3, " ");
7496 sprintf(buf4, " ");
7497
7498 // warn if range extends beyond last tile
7499 sprintf(buf4, "Some tiles will not be %s", move?"moved.":"copied.");
7500
7501 if(dest_last>=NEWMAXTILES)
7502 {
7503 sprintf(buf4, "%s operation cancelled.", move?"Move":"Copy");
7504 jwin_alert("Destination Error", "The destination extends beyond", "the last available tile row.", buf4, "&OK", NULL, 'o', 0, get_zc_font(font_lfont));
7505 return false;
7506 //fix this below to allow the operation to complete with a modified start or end instead of just cancelling
7507 //if (jwin_alert("Destination Error", "The destination extends beyond", "the last available tile row.", buf4, "&OK", "&Cancel", 'o', 'c', get_zc_font(font_lfont))==2)
7508 // {
7509 // return false;
7510 // }
7511 }
7512
7513
7514 TileMoveUndo on_undo;
7515 // Overwrite warnings
7516 TileMoveProcess dest{rect, dest_left, dest_top, dest_width, dest_height, dest_first, dest_last};
7517 if(move)
7518 {
7519 TileMoveProcess src{rect, src_left, src_top, src_width, src_height, src_first, src_last};
7520 if(!handle_tile_move(dest, src, dest_first-src_first, on_undo))
7521 return false;
7522 }
7523 else
7524 {
7525 if(!handle_tile_move(dest))
7526 return false;
7527 }
7528 // copy tiles and delete if needed (move)
7529
7530 {
7531 go_tiles();
7532
7533 int32_t diff=dest_first-src_first;
7534
7535 if(rect)
7536 {
7537 for(int32_t r=0; r<rows; ++r)
7538 {
7539 for(int32_t c=0; c<cols; ++c)
7540 {
7541 int32_t dt=(dest_first+((r*TILES_PER_ROW)+c));
7542 int32_t st=(src_first+((r*TILES_PER_ROW)+c));
7543
7544 if(dt>=NEWMAXTILES)
7545 continue;
7546
7547 overlay_tile(newtilebuf,dt,st,cs,backwards);
7548
7549 }
7550 }
7551 }
7552 else
7553 {
7554 for(int32_t c=0; c<copies; ++c)
7555 {
7556 int32_t dt=(dest_first+c);
7557 int32_t st=(src_first+c);
7558
7559 if(dt>=NEWMAXTILES)
7560 continue;
7561
7562 overlay_tile(newtilebuf,dt,st,cs,backwards);
7563
7564 if(move)
7565 {
7566 if(st<dest_first||st>(dest_first+c-1))
7567 reset_tile(newtilebuf, st, tf4Bit);
7568 }
7569 }
7570 }
7571 }
7572
7573 //now that tiles have moved, fix these buffers -DD
7574 register_blank_tiles();
7575 register_used_tiles();
7576
7577 if(move)
7578 last_tile_move_list = std::move(on_undo);
7579 return true;
7580 }
7581 //
7582 bool do_movetile_united(tile_move_data const& tmd)
7583 {
7584 char buf2[80], buf3[80], buf4[80];
7585 sprintf(buf2, " ");
7586 sprintf(buf3, " ");
7587 sprintf(buf4, " ");
7588
7589 // warn if range extends beyond last tile
7590 sprintf(buf4, "Some tiles will not be %s", tmd.move?"moved.":"copied.");
7591
7592 if(tmd.dest_last>=NEWMAXTILES)
7593 {
7594 sprintf(buf4, "%s operation cancelled.", tmd.move?"Move":"Copy");
7595 jwin_alert("Destination Error", "The destination extends beyond", "the last available tile row.", buf4, "&OK", NULL, 'o', 0, get_zc_font(font_lfont));
7596 return false;
7597 }
7598
7599 TileMoveUndo on_undo;
7600 // Overwrite warnings
7601 TileMoveProcess dest{tmd.rect, tmd.dest_left, tmd.dest_top, tmd.dest_width, tmd.dest_height, tmd.dest_first, tmd.dest_last};
7602 if(tmd.move)
7603 {
7604 TileMoveProcess src{tmd.rect, tmd.src_left, tmd.src_top, tmd.src_width, tmd.src_height, tmd.src_first, tmd.src_last};
7605 if(!handle_tile_move(dest, src, tmd.dest_first-tmd.src_first, on_undo))
7606 return false;
7607 }
7608 else
7609 {
7610 if(!handle_tile_move(dest))
7611 return false;
7612 }
7613
7614 // copy tiles and delete if needed (tmd.move)
7615 {
7616 go_tiles();
7617
7618 if(tmd.rect)
7619 {
7620 for(int32_t r=0; r<tmd.rows; ++r)
7621 {
7622 for(int32_t c=0; c<tmd.cols; ++c)
7623 {
7624 int32_t dt=(tmd.dest_first+((r*TILES_PER_ROW)+c));
7625 int32_t st=(tmd.src_first+((r*TILES_PER_ROW)+c));
7626
7627 if(dt>=NEWMAXTILES)
7628 continue;
7629
7630 reset_tile(newtilebuf, dt, newundotilebuf[st].format);
7631
7632 for(int32_t j=0; j<tilesize(newundotilebuf[st].format); j++)
7633 {
7634 newtilebuf[dt].data[j]=newundotilebuf[st].data[j];
7635 }
7636
7637 if(tmd.move)
7638 {
7639 if((st<tmd.dest_first||st>tmd.dest_first+((tmd.rows-1)*TILES_PER_ROW)+(tmd.cols-1)))
7640 reset_tile(newtilebuf, st, tf4Bit);
7641 else
7642 {
7643 int32_t destLeft=tmd.dest_first%TILES_PER_ROW;
7644 int32_t destRight=(tmd.dest_first+tmd.cols-1)%TILES_PER_ROW;
7645 if(destLeft<=destRight)
7646 {
7647 if(st%TILES_PER_ROW<destLeft || st%TILES_PER_ROW>destRight)
7648 reset_tile(newtilebuf, st, tf4Bit);
7649 }
7650 else // Wrapped around
7651 {
7652 if(st%TILES_PER_ROW<destLeft && st%TILES_PER_ROW>destRight)
7653 reset_tile(newtilebuf, st, tf4Bit);
7654 }
7655 }
7656 }
7657 }
7658 }
7659 }
7660 else
7661 {
7662 for(int32_t c=0; c<tmd.copies; ++c)
7663 {
7664 int32_t dt=(tmd.dest_first+c);
7665 int32_t st=(tmd.src_first+c);
7666
7667 if(dt>=NEWMAXTILES)
7668 continue;
7669
7670 reset_tile(newtilebuf, dt, newundotilebuf[st].format);
7671
7672 for(int32_t j=0; j<tilesize(newundotilebuf[st].format); j++)
7673 {
7674 newtilebuf[dt].data[j]=newundotilebuf[st].data[j];
7675 }
7676
7677 if(tmd.move)
7678 {
7679 if(st<tmd.dest_first||st>(tmd.dest_first+c-1))
7680 reset_tile(newtilebuf, st, tf4Bit);
7681 }
7682 }
7683 }
7684 }
7685
7686 //now that tiles have moved, fix these buffers -DD
7687 register_blank_tiles();
7688 register_used_tiles();
7689
7690 if(tmd.move)
7691 last_tile_move_list = std::move(on_undo);
7692 return true;
7693 }
7694
7695 bool copy_tiles_united(int32_t &tile,int32_t &tile2,int32_t &copy,int32_t &copycnt, bool rect, bool move)
7696 {
7697 bool alt=(key[KEY_ALT]||key[KEY_ALTGR]);
7698 bool shift=(key[KEY_LSHIFT] || key[KEY_RSHIFT]);
7699
7700 // if tile>tile2 then swap them
7701 if(tile>tile2)
7702 {
7703 zc_swap(tile, tile2);
7704 }
7705
7706 // alt=copy from right
7707 // shift=copy from bottom
7708 tile_move_data tmd;
7709
7710 tmd.copies=copycnt;
7711 tmd.dest_first=tile;
7712 tmd.dest_last=tile2;
7713 tmd.src_first=copy;
7714 tmd.src_last=copy+tmd.copies-1;
7715 tmd.rect = rect;
7716 tmd.move = move;
7717
7718 if(rect)
7719 {
7720 tmd.dest_top=TILEROW(tmd.dest_first);
7721 tmd.dest_bottom=TILEROW(tmd.dest_last);
7722 tmd.src_top=TILEROW(tmd.src_first);
7723 tmd.src_bottom=TILEROW(tmd.src_last);
7724
7725 tmd.src_left= zc_min(TILECOL(tmd.src_first),TILECOL(tmd.src_last));
7726 tmd.src_right=zc_max(TILECOL(tmd.src_first),TILECOL(tmd.src_last));
7727 tmd.src_first=(tmd.src_top * TILES_PER_ROW)+tmd.src_left;
7728 tmd.src_last= (tmd.src_bottom*TILES_PER_ROW)+tmd.src_right;
7729
7730 tmd.dest_left= zc_min(TILECOL(tmd.dest_first),TILECOL(tmd.dest_last));
7731 tmd.dest_right=zc_max(TILECOL(tmd.dest_first),TILECOL(tmd.dest_last));
7732 tmd.dest_first=(tmd.dest_top * TILES_PER_ROW)+tmd.dest_left;
7733 tmd.dest_last= (tmd.dest_bottom*TILES_PER_ROW)+tmd.dest_right;
7734
7735 //if no dest range set, then set one
7736 if((tmd.dest_first==tmd.dest_last)&&(tmd.src_first!=tmd.src_last))
7737 {
7738 if(alt)
7739 {
7740 tmd.dest_left=tmd.dest_right-(tmd.src_right-tmd.src_left);
7741 }
7742 else
7743 {
7744 tmd.dest_right=tmd.dest_left+(tmd.src_right-tmd.src_left);
7745 }
7746
7747 if(shift)
7748 {
7749 tmd.dest_top=tmd.dest_bottom-(tmd.src_bottom-tmd.src_top);
7750 }
7751 else
7752 {
7753 tmd.dest_bottom=tmd.dest_top+(tmd.src_bottom-tmd.src_top);
7754 }
7755
7756 tmd.dest_first=(tmd.dest_top * TILES_PER_ROW)+tmd.dest_left;
7757 tmd.dest_last= (tmd.dest_bottom*TILES_PER_ROW)+tmd.dest_right;
7758 }
7759 else
7760 {
7761 if(tmd.dest_right-tmd.dest_left<tmd.src_right-tmd.src_left) //destination is shorter than source
7762 {
7763 if(alt) //copy from right tile instead of left
7764 {
7765 tmd.src_left=tmd.src_right-(tmd.dest_right-tmd.dest_left);
7766 }
7767 else //copy from left tile
7768 {
7769 tmd.src_right=tmd.src_left+(tmd.dest_right-tmd.dest_left);
7770 }
7771 }
7772 else if(tmd.dest_right-tmd.dest_left>tmd.src_right-tmd.src_left) //destination is longer than source
7773 {
7774 if(alt) //copy from right tile instead of left
7775 {
7776 tmd.dest_left=tmd.dest_right-(tmd.src_right-tmd.src_left);
7777 }
7778 else //copy from left tile
7779 {
7780 tmd.dest_right=tmd.dest_left+(tmd.src_right-tmd.src_left);
7781 }
7782 }
7783
7784 if(tmd.dest_bottom-tmd.dest_top<tmd.src_bottom-tmd.src_top) //destination is shorter than source
7785 {
7786 if(shift) //copy from bottom tile instead of top
7787 {
7788 tmd.src_top=tmd.src_bottom-(tmd.dest_bottom-tmd.dest_top);
7789 }
7790 else //copy from top tile
7791 {
7792 tmd.src_bottom=tmd.src_top+(tmd.dest_bottom-tmd.dest_top);
7793 }
7794 }
7795 else if(tmd.dest_bottom-tmd.dest_top>tmd.src_bottom-tmd.src_top) //destination is longer than source
7796 {
7797 if(shift) //copy from bottom tile instead of top
7798 {
7799 tmd.dest_top=tmd.dest_bottom-(tmd.src_bottom-tmd.src_top);
7800 }
7801 else //copy from top tile
7802 {
7803 tmd.dest_bottom=tmd.dest_top+(tmd.src_bottom-tmd.src_top);
7804 }
7805 }
7806
7807 tmd.src_first=(tmd.src_top * TILES_PER_ROW)+tmd.src_left;
7808 tmd.src_last= (tmd.src_bottom*TILES_PER_ROW)+tmd.src_right;
7809 tmd.dest_first=(tmd.dest_top * TILES_PER_ROW)+tmd.dest_left;
7810 tmd.dest_last= (tmd.dest_bottom*TILES_PER_ROW)+tmd.dest_right;
7811 }
7812
7813 tmd.cols=tmd.src_right-tmd.src_left+1;
7814 tmd.rows=tmd.src_bottom-tmd.src_top+1;
7815
7816 tmd.dest_width=tmd.dest_right-tmd.dest_left+1;
7817 tmd.dest_height=tmd.dest_bottom-tmd.dest_top+1;
7818 tmd.src_width=tmd.src_right-tmd.src_left+1;
7819 tmd.src_height=tmd.src_bottom-tmd.src_top+1;
7820
7821 }
7822 else //!rect
7823 {
7824 //if no dest range set, then set one
7825 if((tmd.dest_first==tmd.dest_last)&&(tmd.src_first!=tmd.src_last))
7826 {
7827 if(alt)
7828 {
7829 tmd.dest_first=tmd.dest_last-(tmd.src_last-tmd.src_first);
7830 }
7831 else
7832 {
7833 tmd.dest_last=tmd.dest_first+(tmd.src_last-tmd.src_first);
7834 }
7835 }
7836 else
7837 {
7838 if(tmd.dest_last-tmd.dest_first<tmd.src_last-tmd.src_first) //destination is shorter than source
7839 {
7840 if(alt) //copy from last tile instead of first
7841 {
7842 tmd.src_first=tmd.src_last-(tmd.dest_last-tmd.dest_first);
7843 }
7844 else //copy from first tile
7845 {
7846 tmd.src_last=tmd.src_first+(tmd.dest_last-tmd.dest_first);
7847 }
7848 }
7849 else if(tmd.dest_last-tmd.dest_first>tmd.src_last-tmd.src_first) //destination is longer than source
7850 {
7851 if(alt) //copy from last tile instead of first
7852 {
7853 tmd.dest_first=tmd.dest_last-(tmd.src_last-tmd.src_first);
7854 }
7855 else //copy from first tile
7856 {
7857 tmd.dest_last=tmd.dest_first+(tmd.src_last-tmd.src_first);
7858 }
7859 }
7860 }
7861
7862 tmd.copies=tmd.dest_last-tmd.dest_first+1;
7863 }
7864
7865 return do_movetile_united(tmd);
7866 }
7867
7868 //
7869
7870 bool copy_tiles_united_floodfill(int32_t &tile,int32_t &tile2,int32_t &copy,int32_t &copycnt, bool rect, bool move)
7871 {
7872 assert(!move); //not implemented
7873
7874 // if tile>tile2 then swap them
7875 if(tile>tile2)
7876 {
7877 zc_swap(tile, tile2);
7878 }
7879
7880 tile_move_data tmd;
7881 tmd.copies=copycnt;
7882 tmd.dest_first=tile;
7883 tmd.dest_last=tile2;
7884 tmd.src_first=copy;
7885 tmd.src_last=copy+tmd.copies-1;
7886
7887
7888
7889 if(rect)
7890 {
7891 tmd.dest_top=TILEROW(tmd.dest_first);
7892 tmd.dest_bottom=TILEROW(tmd.dest_last);
7893 //tmd.src_top=TILEROW(tmd.src_first);
7894 //tmd.src_bottom=TILEROW(tmd.src_last);
7895
7896 //tmd.src_left= zc_min(TILECOL(tmd.src_first),TILECOL(tmd.src_last));
7897 //tmd.src_right=zc_max(TILECOL(tmd.src_first),TILECOL(tmd.src_last));
7898 //tmd.src_first=(tmd.src_top * TILES_PER_ROW)+tmd.src_left;
7899 //tmd.src_last= (tmd.src_bottom*TILES_PER_ROW)+tmd.src_right;
7900
7901 tmd.dest_left= zc_min(TILECOL(tmd.dest_first),TILECOL(tmd.dest_last));
7902 tmd.dest_right=zc_max(TILECOL(tmd.dest_first),TILECOL(tmd.dest_last));
7903 tmd.dest_first=(tmd.dest_top * TILES_PER_ROW)+tmd.dest_left;
7904 tmd.dest_last= (tmd.dest_bottom*TILES_PER_ROW)+tmd.dest_right;
7905
7906
7907
7908
7909 tmd.dest_width=tmd.dest_right-tmd.dest_left;
7910 tmd.dest_height=tmd.dest_bottom-tmd.dest_top;
7911
7912 tmd.cols=tmd.dest_width+1;
7913 tmd.rows=tmd.dest_height+1;
7914
7915 al_trace("tmd.rows: %d\n", tmd.rows);
7916 al_trace("tmd.cols: %d\n", tmd.cols);
7917
7918
7919 }
7920 else //!rect
7921 {
7922 tmd.copies=tmd.dest_last-tmd.dest_first+1;
7923 }
7924
7925
7926
7927 char buf2[80], buf3[80], buf4[80];
7928 sprintf(buf2, " ");
7929 sprintf(buf3, " ");
7930 sprintf(buf4, " ");
7931
7932 // warn if range extends beyond last tile
7933 sprintf(buf4, "Some tiles will not be %s", move?"moved.":"copied.");
7934
7935 if(tmd.dest_last>=NEWMAXTILES)
7936 {
7937 sprintf(buf4, "%s operation cancelled.", move?"Move":"Copy");
7938 jwin_alert("Destination Error", "The destination extends beyond", "the last available tile row.", buf4, "&OK", NULL, 'o', 0, get_zc_font(font_lfont));
7939 return false;
7940 //fix this below to allow the operation to complete with a modified start or end instead of just cancelling
7941 //if (jwin_alert("Destination Error", "The destination extends beyond", "the last available tile row.", buf4, "&OK", "&Cancel", 'o', 'c', get_zc_font(font_lfont))==2)
7942 // {
7943 // return false;
7944 // }
7945 }
7946
7947 TileMoveUndo on_undo;
7948 // Overwrite warnings
7949 TileMoveProcess dest{tmd.rect, tmd.dest_left, tmd.dest_top, tmd.dest_width, tmd.dest_height, tmd.dest_first, tmd.dest_last};
7950 if(tmd.move)
7951 {
7952 TileMoveProcess src{tmd.rect, tmd.src_left, tmd.src_top, tmd.src_width, tmd.src_height, tmd.src_first, tmd.src_last};
7953 if(!handle_tile_move(dest, src, tmd.dest_first-tmd.src_first, on_undo))
7954 return false;
7955 }
7956 else
7957 {
7958 if(!handle_tile_move(dest))
7959 return false;
7960 }
7961
7962 // copy tiles and delete if needed (move)
7963
7964 {
7965 go_tiles();
7966
7967 int32_t diff=tmd.dest_first-tmd.src_first;
7968
7969 if(rect)
7970 {
7971 al_trace("floodfill, rect\n");
7972 al_trace("tmd.rows: %d\n", tmd.rows);
7973 al_trace("tmd.cols: %d\n", tmd.cols);
7974 for(int32_t r=0; r<tmd.rows; ++r)
7975 {
7976 for(int32_t c=0; c<tmd.cols; ++c)
7977 {
7978 int32_t dt=(tmd.dest_first+((r*TILES_PER_ROW)+c));
7979 //int32_t st=(tmd.src_first+((r*TILES_PER_ROW)+c));
7980
7981 if(dt>=NEWMAXTILES)
7982 continue;
7983
7984 reset_tile(newtilebuf, dt, newundotilebuf[copy].format);
7985
7986 for(int32_t j=0; j<tilesize(newundotilebuf[copy].format); j++)
7987 {
7988 newtilebuf[dt].data[j]=newundotilebuf[copy].data[j];
7989 }
7990 }
7991 }
7992 }
7993 else
7994 {
7995 for(int32_t c=0; c<tmd.copies; ++c)
7996 {
7997 int32_t dt=(tmd.dest_first+c);
7998 int32_t st=(tmd.src_first+c);
7999
8000 if(dt>=NEWMAXTILES)
8001 continue;
8002
8003 reset_tile(newtilebuf, dt, newundotilebuf[copy].format);
8004
8005 for(int32_t j=0; j<tilesize(newundotilebuf[copy].format); j++)
8006 {
8007 newtilebuf[dt].data[j]=newundotilebuf[copy].data[j];
8008 }
8009
8010 }
8011 }
8012 }
8013
8014 //now that tiles have moved, fix these buffers -DD
8015 register_blank_tiles();
8016 register_used_tiles();
8017
8018 if(tmd.move)
8019 last_tile_move_list = std::move(on_undo);
8020 return true;
8021 }
8022 //
8023
8024 bool copy_tiles_floodfill(int32_t &tile,int32_t &tile2,int32_t &copy,int32_t &copycnt, bool rect_sel, bool move)
8025 {
8026 al_trace("Floodfill Psste\n");
8027 bool ctrl=(CHECK_CTRL_CMD);
8028 bool copied=false;
8029 copied=copy_tiles_united_floodfill(tile,tile2,copy,copycnt,rect_sel,move);
8030
8031 if(copied)
8032 {
8033 if(!ctrl)
8034 {
8035 copy=-1;
8036 tile2=tile;
8037 }
8038
8039 saved=false;
8040 }
8041
8042 return copied;
8043 }
8044
8045 bool copy_tiles(int32_t &tile,int32_t &tile2,int32_t &copy,int32_t &copycnt, bool rect_sel, bool move)
8046 {
8047 bool ctrl=(CHECK_CTRL_CMD);
8048 bool copied=false;
8049 copied=copy_tiles_united(tile,tile2,copy,copycnt,rect_sel,move);
8050
8051 if(copied)
8052 {
8053 if(!ctrl)
8054 {
8055 copy=-1;
8056 tile2=tile;
8057 }
8058
8059 saved=false;
8060 }
8061
8062 return copied;
8063 }
8064
8065 bool scale_or_rotate_tiles(int32_t &tile, int32_t &tile2, int32_t &cs, bool rotate)
8066 {
8067 // if tile>tile2 then swap them
8068 if(tile>tile2)
8069 {
8070 zc_swap(tile, tile2);
8071 }
8072 int32_t src_top = TILEROW(tile);
8073 int32_t src_bottom = TILEROW(tile2);
8074 int32_t src_left = zc_min(TILECOL(tile),TILECOL(tile2));
8075 int32_t src_right = zc_max(TILECOL(tile),TILECOL(tile2));
8076 int32_t src_first = (src_top * TILES_PER_ROW)+src_left;
8077 int32_t src_last = (src_bottom*TILES_PER_ROW)+src_right;
8078
8079 int32_t src_width = src_right-src_left+1,
8080 src_height = src_bottom-src_top+1;
8081 int32_t dest_width = src_width, dest_height = src_height;
8082 zfix dest_rot = 0_zf;
8083 if(rotate)
8084 RotateTileDialog(&dest_width, &dest_height, &dest_rot).show();
8085 else
8086 ScaleTileDialog(&dest_width, &dest_height).show();
8087 if (rotate)
8088 {
8089 if (dest_rot == 0) return false;
8090 }
8091 else
8092 {
8093 if (dest_width == src_width && dest_height == src_height) return false; //no scaling
8094 }
8095 dest_width = vbound(dest_width, 1, 20);
8096 dest_height = vbound(dest_height, 1, 20);
8097
8098 int32_t dest_top = src_top;
8099 int32_t dest_bottom = src_top+dest_height-1;
8100 int32_t dest_left = src_left;
8101 int32_t dest_right = src_left+dest_width-1;
8102 int32_t dest_first = src_first;
8103 int32_t dest_last = (dest_bottom*TILES_PER_ROW)+dest_right;
8104
8105
8106 if(dest_last>=NEWMAXTILES)
8107 {
8108 InfoDialog("Destination Error", "The destination extends beyond the last available tile row. Scale operation cancelled.").show();
8109 return false;
8110 }
8111
8112 // Overwrite warnings
8113 if(!handle_tile_move({true, dest_left, dest_top, dest_width, dest_height, dest_first, dest_last}))
8114 return false;
8115
8116 //Do the rotate
8117 {
8118 go_tiles();
8119
8120 int32_t diff=dest_first-src_first;
8121 BITMAP *srcbmp = create_bitmap_ex(8,src_width*16,src_height*16),
8122 *destbmp = create_bitmap_ex(8,dest_width*16,dest_height*16);
8123 clear_bitmap(srcbmp); clear_bitmap(destbmp);
8124 overtileblock16(srcbmp, src_first, 0, 0, src_width, src_height, cs, 0);
8125 bool is8bit = newtilebuf[src_first].format == tf8Bit;
8126 if (rotate)
8127 {
8128 rotate_sprite(destbmp, srcbmp, 0, 0, ftofix(dest_rot * 0.7111111111111));
8129 }
8130 else
8131 {
8132 stretch_blit(srcbmp, destbmp, 0, 0, srcbmp->w, srcbmp->h,
8133 0, 0, destbmp->w, destbmp->h);
8134 }
8135 int32_t mhei = zc_max(src_height,dest_height),
8136 mwid = zc_max(src_width, dest_width);
8137 for(int32_t r=0; r<mhei; ++r)
8138 {
8139 for(int32_t c=0; c<mwid; ++c)
8140 {
8141 int32_t dt=(dest_first+((r*TILES_PER_ROW)+c));
8142
8143 if(dt>=NEWMAXTILES)
8144 continue;
8145 if(r < dest_height && c < dest_width)
8146 {
8147 write_tile(newtilebuf, destbmp, dt, c*16, r*16, is8bit, false);
8148 }
8149 else reset_tile(newtilebuf, dt, tf4Bit);
8150 }
8151 }
8152 }
8153
8154 register_blank_tiles();
8155 register_used_tiles();
8156 return true;
8157 }
8158
8159 void copy_combos(int32_t &tile,int32_t &tile2,int32_t &copy,int32_t &copycnt, bool masscopy)
8160 {
8161 //these 2 shouldn't be needed, but just to be safe...
8162 reset_combo_animations();
8163 reset_combo_animations2();
8164
8165 if(tile2<tile)
8166 {
8167 zc_swap(tile,tile2);
8168 }
8169
8170 auto first = tile;
8171 auto last = masscopy ? tile2 : first + copycnt-1;
8172 if(!handle_combo_move({first,last}))
8173 return;
8174
8175 if(!masscopy)
8176 {
8177 if(tile==copy)
8178 {
8179 copy=-1;
8180 tile2=tile;
8181 return;
8182 }
8183
8184 // go_combos(); // commented because caller does it for us
8185 //if copying to an earlier combo, copy from left to right
8186 //otherwise, copy from right to left
8187 for(int32_t t=(tile<copy)?0:(copycnt-1); (tile<copy)?(t<copycnt):(t>=0); (tile<copy)?(t++):(t--))
8188 {
8189 if(tile+t < MAXCOMBOS)
8190 {
8191 combobuf[tile+t]=combobuf[copy+t];
8192 }
8193 }
8194
8195 copy=-1;
8196 tile2=tile;
8197 saved=false;
8198 }
8199 else
8200 {
8201 // go_combos();
8202 int32_t src=copy, dest=tile;
8203
8204 do
8205 {
8206 combobuf[dest]=combobuf[src];
8207 ++src;
8208 ++dest;
8209
8210 if((src-copy)==copycnt) src=copy;
8211 }
8212 while(dest<=tile2);
8213
8214 copy=-1;
8215 tile2=tile;
8216 saved=false;
8217 }
8218
8219 setup_combo_animations();
8220 setup_combo_animations2();
8221 }
8222
8223 bool do_movecombo(combo_move_data const& cmd, ComboMoveUndo& on_undo, bool is_undoing)
8224 {
8225 reset_combo_animations();
8226 reset_combo_animations2();
8227 go_combos();
8228
8229 auto diff = cmd.tile - cmd.copy1;
8230 if(is_undoing)
8231 on_undo.undo();
8232 else if(!handle_combo_move({cmd.tile,cmd.tile+cmd.copycnt-1},{cmd.copy1,cmd.copy1+cmd.copycnt-1}, diff, on_undo))
8233 return false;
8234
8235 for(int32_t t=(cmd.tile<cmd.copy1)?0:(cmd.copycnt-1); (cmd.tile<cmd.copy1)?(t<cmd.copycnt):(t>=0); (cmd.tile<cmd.copy1)?(t++):(t--))
8236 {
8237 if(cmd.tile+t < MAXCOMBOS)
8238 {
8239 combobuf[cmd.tile+t]=combobuf[cmd.copy1+t];
8240 clear_combo(cmd.copy1+t);
8241 }
8242 }
8243
8244 setup_combo_animations();
8245 setup_combo_animations2();
8246 saved=false;
8247 return true;
8248 }
8249
8250 void move_combos(int32_t &tile,int32_t &tile2,int32_t &copy,int32_t &copycnt)
8251 {
8252 if(tile2<tile)
8253 {
8254 zc_swap(tile,tile2);
8255 }
8256
8257 if(tile==copy)
8258 {
8259 copy=-1;
8260 tile2=tile;
8261 return;
8262 }
8263
8264 combo_move_data cmd;
8265 cmd.tile = tile;
8266 cmd.tile2 = tile2;
8267 cmd.copy1 = copy;
8268 cmd.copycnt = copycnt;
8269
8270 ComboMoveUndo on_undo;
8271 if(!do_movecombo(cmd, on_undo))
8272 return;
8273 last_combo_move_list = std::move(on_undo);
8274 copy=-1;
8275 tile2=tile;
8276 }
8277
8278 void do_delete_tiles(int32_t firsttile, int32_t lasttile, bool rect_sel)
8279 {
8280 if(firsttile > lasttile)
8281 zc_swap(firsttile,lasttile);
8282 int32_t coldiff = 0;
8283 if(rect_sel && TILECOL(firsttile)>TILECOL(lasttile))
8284 {
8285 coldiff=TILECOL(firsttile)-TILECOL(lasttile);
8286 firsttile-=coldiff;
8287 lasttile+=coldiff;
8288 }
8289 for(int32_t t=firsttile; t<=lasttile; ++t)
8290 if(!rect_sel ||
8291 ((TILECOL(t)>=TILECOL(firsttile)) &&
8292 (TILECOL(t)<=TILECOL(lasttile))))
8293 reset_tile(newtilebuf, t, tf4Bit);
8294 saved=false;
8295 register_blank_tiles();
8296 }
8297
8298 void delete_tiles(int32_t &tile,int32_t &tile2,bool rect_sel)
8299 {
8300 char buf[40];
8301
8302 if(tile==tile2)
8303 {
8304 sprintf(buf,"Delete tile %d?",tile);
8305 }
8306 else
8307 {
8308 sprintf(buf,"Delete tiles %d-%d?",zc_min(tile,tile2),zc_max(tile,tile2));
8309 }
8310
8311 if(jwin_alert("Confirm Delete",buf,NULL,NULL,"&Yes","&No",'y','n',get_zc_font(font_lfont))==1)
8312 {
8313 int32_t firsttile=zc_min(tile,tile2), lasttile=zc_max(tile,tile2), coldiff=0;
8314
8315 go_tiles();
8316
8317 //if copying to an earlier tile, copy from left to right
8318 //otherwise, copy from right to left
8319 do_delete_tiles(firsttile, lasttile, rect_sel);
8320
8321 tile=tile2=zc_min(tile,tile2);
8322 saved=false;
8323 register_blank_tiles();
8324 }
8325 }
8326
8327 void overlay_tile2(int32_t dest,int32_t src,int32_t cs,bool backwards)
8328 {
8329 byte buf[256];
8330 go_tiles();
8331
8332 unpack_tile(newtilebuf, dest, 0, false);
8333
8334 for(int32_t i=0; i<256; i++)
8335 buf[i] = unpackbuf[i];
8336
8337 unpack_tile(newtilebuf, src, 0, false);
8338
8339 if(newtilebuf[src].format>tf4Bit)
8340 {
8341 cs=0;
8342 }
8343
8344 cs &= 15;
8345 cs <<= CSET_SHFT;
8346
8347 for(int32_t i=0; i<256; i++)
8348 {
8349 if(backwards)
8350 {
8351 if(!buf[i])
8352 {
8353 buf[i] = unpackbuf[i]+cs;
8354 }
8355 }
8356 else
8357 {
8358 if(unpackbuf[i])
8359 {
8360 buf[i] = unpackbuf[i]+cs;
8361 }
8362 }
8363 }
8364
8365 pack_tile(newtilebuf, buf,dest);
8366 saved=false;
8367 }
8368
8369 void mass_overlay_tile(int32_t dest1, int32_t dest2, int32_t src, int32_t cs, bool backwards, bool rect_sel)
8370 {
8371 //byte buf[256];
8372 go_tiles();
8373
8374 if(!rect_sel)
8375 {
8376 for(int32_t d=dest1; d <= dest2; ++d)
8377 {
8378 /*unpack_tile(newtilebuf, d, 0, false);
8379
8380 for(int32_t i=0; i<256; i++)
8381 {
8382 if(!backwards)
8383 {
8384 if(!buf[i])
8385 {
8386 buf[i] = unpackbuf[i] + cs;
8387 }
8388 }
8389 else
8390 {
8391 if(unpackbuf[i])
8392 {
8393 buf[i] = unpackbuf[i] + cs;
8394 }
8395 }
8396 }
8397
8398 pack_tile(newtilebuf, buf,d);
8399 */
8400
8401 overlay_tile(newtilebuf,d,src,cs,backwards);
8402
8403 if(!blank_tile_table[src])
8404 {
8405 blank_tile_table[d]=false;
8406 }
8407 }
8408 }
8409 else
8410 {
8411 int32_t rmin=zc_min(TILEROW(dest1),TILEROW(dest2));
8412 int32_t rmax=zc_max(TILEROW(dest1),TILEROW(dest2));
8413 int32_t cmin=zc_min(TILECOL(dest1),TILECOL(dest2));
8414 int32_t cmax=zc_max(TILECOL(dest1),TILECOL(dest2));
8415 int32_t d=0;
8416
8417 for(int32_t j=cmin; j<=cmax; ++j)
8418 {
8419 for(int32_t k=rmin; k<=rmax; ++k)
8420 {
8421 d=j+TILES_PER_ROW*k;
8422 /*unpack_tile(newtilebuf, d, 0, false);
8423
8424 for(int32_t i=0; i<256; i++)
8425 {
8426 if(!backwards)
8427 {
8428 if(!buf[i])
8429 {
8430 buf[i] = unpackbuf[i] + cs;
8431 }
8432 }
8433 else
8434 {
8435 if(unpackbuf[i])
8436 {
8437 buf[i] = unpackbuf[i] + cs;
8438 }
8439 }
8440 }
8441
8442 pack_tile(newtilebuf, buf,d);
8443 */
8444
8445 overlay_tile(newtilebuf,d,src,cs,backwards);
8446
8447 if(!blank_tile_table[src])
8448 {
8449 blank_tile_table[d]=false;
8450 }
8451 }
8452 }
8453 }
8454
8455 return;
8456 }
8457
8458 void sel_tile(int32_t &tile, int32_t &tile2, int32_t &first, int32_t type, int32_t s)
8459 {
8460 tile+=s;
8461 bound(tile,0,NEWMAXTILES-1);
8462
8463 if(type!=0 || !(key[KEY_LSHIFT] || key[KEY_RSHIFT]))
8464 tile2 = tile;
8465
8466 first = tile - (tile%TILES_PER_PAGE);
8467 }
8468
8469 void convert_tile(int32_t t, int32_t bp2, int32_t cs, bool shift, bool alt)
8470 {
8471 int32_t cst;
8472
8473 switch(bp2)
8474 {
8475 case tf4Bit:
8476 switch(newtilebuf[t].format)
8477 {
8478 case tf4Bit:
8479 //already in the right format
8480 break;
8481
8482 case tf8Bit:
8483 unpack_tile(newtilebuf, t, 0, true);
8484
8485 if(alt) //reduce
8486 {
8487 for(int32_t i=0; i<256; i++)
8488 {
8489 if(!shift||unpackbuf[i]!=0)
8490 {
8491 unpackbuf[i]=(cset_reduce_table[unpackbuf[i]]);
8492 }
8493 }
8494 }
8495 else //truncate
8496 {
8497 for(int32_t i=0; i<256; i++)
8498 {
8499 unpackbuf[i]&=15;
8500 }
8501 }
8502
8503 reset_tile(newtilebuf, t, tf4Bit);
8504 pack_tile(newtilebuf, unpackbuf, t);
8505 break;
8506 }
8507
8508 break;
8509
8510 case tf8Bit:
8511 switch(newtilebuf[t].format)
8512 {
8513 case tf4Bit:
8514 unpack_tile(newtilebuf, t, 0, true);
8515 cst = cs&15;
8516 cst <<= CSET_SHFT;
8517
8518 for(int32_t i=0; i<256; i++)
8519 {
8520 if(!shift||unpackbuf[i]!=0)
8521 {
8522 unpackbuf[i]+=cst;
8523 }
8524 }
8525
8526 reset_tile(newtilebuf, t, tf8Bit);
8527 pack_tile(newtilebuf, unpackbuf, t);
8528 break;
8529
8530 case tf8Bit:
8531 //already in the right format
8532 break;
8533 }
8534
8535 break;
8536 }
8537 }
8538
8539 static DIALOG create_relational_tiles_dlg[] =
8540 {
8541 // (dialog proc) (x) (y) (w) (h) (fg) (bg) (key) (flags) (d1) (d2) (dp)
8542 9 { jwin_win_proc, 0, 0, 160, 92, vc(0), vc(11), 0, D_EXIT, 0, 0, (void *) "Tile Setup", NULL, NULL },
8543 9 { jwin_rtext_proc, 74, 28, 48, 8, jwin_pal[jcBOXFG], jwin_pal[jcBOX], 0, 0, 0, 0, (void *) "Frames:", NULL, NULL },
8544 9 { jwin_edit_proc, 78, 24, 48, 16, 0, 0, 0, 0, 6, 0, NULL, NULL, NULL },
8545 9 { jwin_radio_proc, 8, 44, 64, 9, vc(14), vc(1), 0, D_SELECTED, 0, 0, (void *) "Relational", NULL, NULL },
8546 9 { jwin_radio_proc, 68, 44, 64, 9, vc(14), vc(1), 0, 0, 0, 0, (void *) "Dungeon Carving", NULL, NULL },
8547 9 { jwin_button_proc, 10, 66, 61, 21, vc(0), vc(11), 13, D_EXIT, 0, 0, (void *) "OK", NULL, NULL },
8548 9 { jwin_button_proc, 90, 66, 61, 21, vc(0), vc(11), 27, D_EXIT, 0, 0, (void *) "Cancel", NULL, NULL },
8549 9 { d_timer_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL },
8550 9 { NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }
8551 };
8552
8553 void draw_tile_list_window()
8554 {
8555 int32_t w = 640;
8556 int32_t h = 480;
8557
8558 int32_t window_xofs=(zq_screen_w-w-12)>>1;
8559 int32_t window_yofs=(zq_screen_h-h-25-6)>>1;
8560 jwin_draw_win(screen, window_xofs, window_yofs, w+6+6, h+25+6, FR_WIN);
8561 jwin_draw_frame(screen, window_xofs+4, window_yofs+23, w+2+2, h+4+2-64, FR_DEEP);
8562
8563 FONT *oldfont = font;
8564 font = get_zc_font(font_lfont);
8565 jwin_draw_titlebar(screen, window_xofs+3, window_yofs+3, w+6, 18, "Select Tile", true);
8566 font=oldfont;
8567 return;
8568 }
8569
8570 void show_blank_tile(int32_t t)
8571 {
8572 char tbuf[80], tbuf2[80], tbuf3[80];
8573 sprintf(tbuf, "Tile is%s blank.", blank_tile_table[t]?"":" not");
8574 sprintf(tbuf2, "%c %c", blank_tile_quarters_table[t*4]?'X':'-', blank_tile_quarters_table[(t*4)+1]?'X':'-');
8575 sprintf(tbuf3, "%c %c", blank_tile_quarters_table[(t*4)+2]?'X':'-', blank_tile_quarters_table[(t*4)+3]?'X':'-');
8576 jwin_alert("Blank Tile Information",tbuf,tbuf2,tbuf3,"&OK",NULL,13,27,get_zc_font(font_lfont));
8577 }
8578
8579 static void do_convert_tile(int32_t tile, int32_t tile2, int32_t cs, bool rect_sel, int format, bool shift, bool alt, bool skip_prompt = false)
8580 {
8581 int num_bits;
8582 if (format == tf4Bit)
8583 num_bits = 4;
8584 else if (format == tf8Bit)
8585 num_bits = 8;
8586 else assert(false);
8587
8588 char buf[80];
8589 sprintf(buf, "Do you want to convert the selected %s to %d-bit color?", tile==tile2?"tile":"tiles",num_bits);
8590
8591 if (skip_prompt || jwin_alert("Convert Tile?",buf,NULL,NULL,"&Yes","&No",'y','n',get_zc_font(font_lfont))==1)
8592 {
8593 go_tiles();
8594 saved=false;
8595
8596 if(format == tf4Bit)
8597 {
8598 memset(cset_reduce_table, 0, 256);
8599 memset(col_diff,0,3*128);
8600 calc_cset_reduce_table(RAMpal, cs);
8601 }
8602
8603 int32_t firsttile=zc_min(tile,tile2), lasttile=zc_max(tile,tile2), coldiff=0;
8604
8605 if(rect_sel && TILECOL(firsttile)>TILECOL(lasttile))
8606 {
8607 coldiff=TILECOL(firsttile)-TILECOL(lasttile);
8608 firsttile-=coldiff;
8609 lasttile+=coldiff;
8610 }
8611
8612 for(int32_t t=firsttile; t<=lasttile; t++)
8613 if(!rect_sel ||
8614 ((TILECOL(t)>=TILECOL(firsttile)) &&
8615 (TILECOL(t)<=TILECOL(lasttile))))
8616 convert_tile(t, format, cs, shift, alt);
8617
8618 tile=tile2=zc_min(tile,tile2);
8619 }
8620 }
8621
8622
8623 int32_t readtilefile(PACKFILE *f)
8624 {
8625 dword section_version=0;
8626 dword section_cversion=0;
8627 int32_t zversion = 0;
8628 int32_t zbuild = 0;
8629
8630 if(!p_igetl(&zversion,f))
8631 {
8632 return 0;
8633 }
8634 if(!p_igetl(&zbuild,f))
8635 {
8636 return 0;
8637 }
8638 if(!p_igetw(&section_version,f))
8639 {
8640 return 0;
8641 }
8642 if(!p_igetw(&section_cversion,f))
8643 {
8644 return 0;
8645 }
8646 al_trace("readoneweapon section_version: %d\n", section_version);
8647 al_trace("readoneweapon section_cversion: %d\n", section_cversion);
8648
8649 if ( zversion > ZELDA_VERSION )
8650 {
8651 al_trace("Cannot read .ztile packfile made in ZC version (%x) in this version of ZC (%x)\n", zversion, ZELDA_VERSION);
8652 return 0;
8653 }
8654
8655 else if ( ( section_version > V_TILES ) || ( section_version == V_TILES && section_cversion < CV_TILES ) )
8656 {
8657 al_trace("Cannot read .ztile packfile made using V_TILES (%d) subversion (%d)\n", section_version, section_cversion);
8658 return 0;
8659
8660 }
8661 else
8662 {
8663 al_trace("Reading a .ztile packfile made in ZC Version: %x, Build: %d\n", zversion, zbuild);
8664 }
8665
8666 int32_t index = 0;
8667 int32_t count = 0;
8668
8669 //tile id
8670 if(!p_igetl(&index,f))
8671 {
8672 return 0;
8673 }
8674 al_trace("Reading tile: index(%d)\n", index);
8675
8676 //tile count
8677 if(!p_igetl(&count,f))
8678 {
8679 return 0;
8680 }
8681 al_trace("Reading tile: count(%d)\n", count);
8682
8683
8684
8685
8686 for ( int32_t tilect = 0; tilect < count; tilect++ )
8687 {
8688 byte *temp_tile = new byte[tilesize(tf32Bit)];
8689 byte format=tf4Bit;
8690 memset(temp_tile, 0, tilesize(tf32Bit));
8691 if(!p_getc(&format,f))
8692 {
8693 delete[] temp_tile;
8694 return 0;
8695 }
8696
8697
8698 if(!pfread(temp_tile,tilesize(format),f))
8699 {
8700 delete[] temp_tile;
8701 return 0;
8702 }
8703
8704 reset_tile(newtilebuf, index+(tilect), format);
8705 memcpy(newtilebuf[index+(tilect)].data,temp_tile,tilesize(newtilebuf[index+(tilect)].format));
8706 delete[] temp_tile;
8707 }
8708
8709
8710 //::memcpy(&(newtilebuf[tile_index]),&temptile,sizeof(tiledata));
8711
8712 register_blank_tiles();
8713 register_used_tiles();
8714
8715 return 1;
8716
8717 }
8718
8719 int32_t readtilefile_to_location(PACKFILE *f, int32_t start, int32_t skip)
8720 {
8721 dword section_version=0;
8722 dword section_cversion=0;
8723 int32_t zversion = 0;
8724 int32_t zbuild = 0;
8725
8726 if(!p_igetl(&zversion,f))
8727 {
8728 return 0;
8729 }
8730 if(!p_igetl(&zbuild,f))
8731 {
8732 return 0;
8733 }
8734 if(!p_igetw(&section_version,f))
8735 {
8736 return 0;
8737 }
8738 if(!p_igetw(&section_cversion,f))
8739 {
8740 return 0;
8741 }
8742 al_trace("readoneweapon section_version: %d\n", section_version);
8743 al_trace("readoneweapon section_cversion: %d\n", section_cversion);
8744
8745 if ( zversion > ZELDA_VERSION )
8746 {
8747 al_trace("Cannot read .ztile packfile made in ZC version (%x) in this version of ZC (%x)\n", zversion, ZELDA_VERSION);
8748 return 0;
8749 }
8750
8751 else if ( ( section_version > V_TILES ) || ( section_version == V_TILES && section_cversion < CV_TILES ) )
8752 {
8753 al_trace("Cannot read .ztile packfile made using V_TILES (%d) subversion (%d)\n", section_version, section_cversion);
8754 return 0;
8755
8756 }
8757 else
8758 {
8759 al_trace("Reading a .ztile packfile made in ZC Version: %x, Build: %d\n", zversion, zbuild);
8760 }
8761
8762 int32_t index = 0;
8763 int32_t count = 0;
8764
8765 //tile id
8766 if(!p_igetl(&index,f))
8767 {
8768 return 0;
8769 }
8770 al_trace("Reading tile: index(%d)\n", index);
8771
8772 //tile count
8773 if(!p_igetl(&count,f))
8774 {
8775 return 0;
8776 }
8777 al_trace("Reading tile: count(%d)\n", count);
8778
8779
8780 for ( int32_t tilect = 0; tilect < count; tilect++ )
8781 {
8782 byte *temp_tile = new byte[tilesize(tf32Bit)];
8783 byte format=tf4Bit;
8784 memset(temp_tile, 0, tilesize(tf32Bit));
8785 if(!p_getc(&format,f))
8786 {
8787 delete[] temp_tile;
8788 return 0;
8789 }
8790
8791
8792 if(!pfread(temp_tile,tilesize(format),f))
8793 {
8794 delete[] temp_tile;
8795 return 0;
8796 }
8797
8798 reset_tile(newtilebuf, start+(tilect), format);
8799 if ( skip )
8800 {
8801 if ( (start+(tilect)) < skip )
8802 {
8803 delete[] temp_tile;
8804 continue;
8805 }
8806
8807 }
8808 if ( start+(tilect) < NEWMAXTILES )
8809 {
8810 memcpy(newtilebuf[start+(tilect)].data,temp_tile,tilesize(newtilebuf[start+(tilect)].format));
8811 }
8812 delete[] temp_tile;
8813
8814 }
8815
8816
8817 //::memcpy(&(newtilebuf[tile_index]),&temptile,sizeof(tiledata));
8818
8819 register_blank_tiles();
8820 register_used_tiles();
8821
8822 return 1;
8823
8824 }
8825
8826
8827 int32_t readtilefile_to_location(PACKFILE *f, int32_t start)
8828 {
8829 dword section_version=0;
8830 dword section_cversion=0;
8831 int32_t zversion = 0;
8832 int32_t zbuild = 0;
8833
8834 if(!p_igetl(&zversion,f))
8835 {
8836 return 0;
8837 }
8838 if(!p_igetl(&zbuild,f))
8839 {
8840 return 0;
8841 }
8842 if(!p_igetw(&section_version,f))
8843 {
8844 return 0;
8845 }
8846 if(!p_igetw(&section_cversion,f))
8847 {
8848 return 0;
8849 }
8850 al_trace("readoneweapon section_version: %d\n", section_version);
8851 al_trace("readoneweapon section_cversion: %d\n", section_cversion);
8852
8853 if ( zversion > ZELDA_VERSION )
8854 {
8855 al_trace("Cannot read .ztile packfile made in ZC version (%x) in this version of ZC (%x)\n", zversion, ZELDA_VERSION);
8856 return 0;
8857 }
8858
8859 else if ( ( section_version > V_TILES ) || ( section_version == V_TILES && section_cversion < CV_TILES ) )
8860 {
8861 al_trace("Cannot read .ztile packfile made using V_TILES (%d) subversion (%d)\n", section_version, section_cversion);
8862 return 0;
8863
8864 }
8865 else
8866 {
8867 al_trace("Reading a .ztile packfile made in ZC Version: %x, Build: %d\n", zversion, zbuild);
8868 }
8869
8870 int32_t index = 0;
8871 int32_t count = 0;
8872
8873 //tile id
8874 if(!p_igetl(&index,f))
8875 {
8876 return 0;
8877 }
8878 al_trace("Reading tile: index(%d)\n", index);
8879
8880 //tile count
8881 if(!p_igetl(&count,f))
8882 {
8883 return 0;
8884 }
8885 al_trace("Reading tile: count(%d)\n", count);
8886
8887
8888
8889
8890 for ( int32_t tilect = 0; tilect < count; tilect++ )
8891 {
8892 byte *temp_tile = new byte[tilesize(tf32Bit)];
8893 byte format=tf4Bit;
8894 memset(temp_tile, 0, tilesize(tf32Bit));
8895
8896 if(!p_getc(&format,f))
8897 {
8898 delete[] temp_tile;
8899 return 0;
8900 }
8901
8902
8903 if(!pfread(temp_tile,tilesize(format),f))
8904 {
8905 delete[] temp_tile;
8906 return 0;
8907 }
8908
8909 reset_tile(newtilebuf, start+(tilect), format);
8910 if ( start+(tilect) < NEWMAXTILES )
8911 {
8912 memcpy(newtilebuf[start+(tilect)].data,temp_tile,tilesize(newtilebuf[start+(tilect)].format));
8913 }
8914 delete[] temp_tile;
8915 }
8916
8917
8918 //::memcpy(&(newtilebuf[tile_index]),&temptile,sizeof(tiledata));
8919
8920 register_blank_tiles();
8921 register_used_tiles();
8922
8923 return 1;
8924
8925 }
8926 int32_t writetilefile(PACKFILE *f, int32_t index, int32_t count)
8927 {
8928 dword section_version=V_TILES;
8929 dword section_cversion=CV_TILES;
8930 int32_t zversion = ZELDA_VERSION;
8931 int32_t zbuild = VERSION_BUILD;
8932
8933 if(!p_iputl(zversion,f))
8934 {
8935 return 0;
8936 }
8937 if(!p_iputl(zbuild,f))
8938 {
8939 return 0;
8940 }
8941 if(!p_iputw(section_version,f))
8942 {
8943 return 0;
8944 }
8945
8946 if(!p_iputw(section_cversion,f))
8947 {
8948 return 0;
8949 }
8950
8951 //start tile id
8952 if(!p_iputl(index,f))
8953 {
8954 return 0;
8955 }
8956
8957 //count
8958 if(!p_iputl(count,f))
8959 {
8960 return 0;
8961 }
8962
8963 for ( int32_t tilect = 0; tilect < count; tilect++ )
8964 {
8965 if(!p_putc(newtilebuf[index+(tilect)].format,f))
8966 {
8967 return 0;
8968 }
8969 if(!pfwrite(newtilebuf[index+(tilect)].data,tilesize(newtilebuf[index+(tilect)].format),f))
8970 {
8971 return 0;
8972 }
8973 }
8974
8975 return 1;
8976
8977 }
8978
8979 static int32_t _selected_tile=-1, _selected_tcset=-1;
8980 int32_t select_tile(int32_t &tile,int32_t &flip,int32_t type,int32_t &cs,bool edit_cs,int32_t exnow, bool always_use_flip)
8981 {
8982 popup_zqdialog_start();
8983 reset_combo_animations();
8984 reset_combo_animations2();
8985 bound(tile,0,NEWMAXTILES-1);
8986 ex=exnow;
8987 int32_t done=0;
8988 int32_t oflip=flip;
8989 int32_t otile=tile;
8990 int32_t ocs=cs;
8991 int32_t first=(tile/TILES_PER_PAGE)*TILES_PER_PAGE; //first tile on the current page
8992 int32_t copy=-1;
8993 int32_t tile2=tile,copycnt=0;
8994 int32_t tile_clicked=-1;
8995 bool rect_sel=true;
8996 bound(first,0,(TILES_PER_PAGE*TILE_PAGES)-1);
8997 position_mouse_z(0);
8998
8999 go();
9000
9001 register_used_tiles();
9002 int32_t w = 640;
9003 int32_t h = 480;
9004 int32_t window_xofs=(zq_screen_w-w-12)>>1;
9005 int32_t window_yofs=(zq_screen_h-h-25-6)>>1;
9006 int32_t screen_xofs=window_xofs+6;
9007 int32_t screen_yofs=window_yofs+25;
9008 int32_t panel_yofs=3;
9009 int32_t mul = 2;
9010 FONT *tfont = get_zc_font(font_lfont_l);
9011
9012 draw_tile_list_window();
9013 int32_t f=0;
9014 draw_tiles(first,cs,f);
9015
9016 if(type==0)
9017 {
9018 tile_info_0(tile,tile2,cs,copy,copycnt,first/TILES_PER_PAGE,rect_sel);
9019 }
9020 else
9021 {
9022 tile_info_1(otile,oflip,ocs,tile,flip,cs,copy,first/TILES_PER_PAGE, always_use_flip);
9023 }
9024
9025 go_tiles();
9026
9027 while(gui_mouse_b())
9028 {
9029 /* do nothing */
9030 rest(1);
9031 }
9032
9033 bool bdown=false;
9034
9035 #define FOREACH_START(_t) \
9036 { \
9037 int32_t _first, _last; \
9038 if(is_rect) \
9039 { \
9040 _first=top*TILES_PER_ROW+left; \
9041 _last=_first+rows*TILES_PER_ROW|+columns-1; \
9042 } \
9043 else \
9044 { \
9045 _first=zc_min(tile, tile2); \
9046 _last=zc_max(tile, tile2); \
9047 } \
9048 for(int32_t _t=_first; _t<=_last; _t++) \
9049 { \
9050 if(is_rect) \
9051 { \
9052 int32_t row=TILEROW(_t); \
9053 if(row<top || row>=top+rows) \
9054 continue; \
9055 int32_t col=TILECOL(_t); \
9056 if(col<left || col>=left+columns) \
9057 continue; \
9058 } \
9059
9060 #define FOREACH_END\
9061 } \
9062 }
9063
9064 bool did_snap = false;
9065 int otl = tile, otl2 = tile2;
9066 do
9067 {
9068 HANDLE_CLOSE_ZQDLG();
9069 if(exiting_program) break;
9070 rest(4);
9071 int32_t top=TILEROW(zc_min(tile, tile2));
9072 int32_t left=zc_min(TILECOL(tile), TILECOL(tile2));
9073 int32_t rows=TILEROW(zc_max(tile, tile2))-top+1;
9074 int32_t columns=zc_max(TILECOL(tile), TILECOL(tile2))-left+1;
9075 bool is_rect=(rows==1)||(columns==TILES_PER_ROW)||rect_sel;
9076 bool redraw=false;
9077
9078 if(mouse_z!=0)
9079 {
9080 sel_tile(tile,tile2,first,type,((mouse_z/abs(mouse_z))*(-1)*TILES_PER_PAGE));
9081 position_mouse_z(0);
9082 redraw=true;
9083 }
9084
9085 if(keypressed())
9086 {
9087 switch(readkey()>>8)
9088 {
9089 case KEY_ENTER_PAD:
9090 case KEY_ENTER:
9091 done=2;
9092 break;
9093
9094 case KEY_ESC:
9095 done=1;
9096 break;
9097
9098 case KEY_F1:
9099 onHelp();
9100 break;
9101
9102 case KEY_EQUALS:
9103 case KEY_PLUS_PAD:
9104 {
9105 if(CHECK_CTRL_CMD ||
9106 key[KEY_ALT] || key[KEY_ALTGR])
9107 {
9108 FOREACH_START(t)
9109 if(key[KEY_ALT] || key[KEY_ALTGR])
9110 shift_tile_colors(t, 16, false);
9111 else
9112 shift_tile_colors(t, 1, key[KEY_LSHIFT] || key[KEY_RSHIFT]);
9113 FOREACH_END
9114
9115 register_blank_tiles();
9116 }
9117 else if(edit_cs)
9118 cs = (cs<13) ? cs+1:0;
9119
9120 redraw=true;
9121 break;
9122 }
9123
9124 case KEY_Z:
9125 case KEY_F12:
9126 {
9127 if(!did_snap)
9128 {
9129 //Export tile page as screenshot
9130 PALETTE temppal;
9131 get_palette(temppal);
9132 BITMAP *tempbmp=create_bitmap_ex(8,16*TILES_PER_ROW, 16*TILE_ROWS_PER_PAGE);
9133 draw_tiles(tempbmp,first,cs,f,false,true);
9134 save_bitmap(getSnapName(), tempbmp, RAMpal);
9135 destroy_bitmap(tempbmp);
9136
9137 redraw = true;
9138 did_snap = true;
9139 }
9140 break;
9141 }
9142
9143 case KEY_S:
9144 {
9145 if(!prompt_for_new_file_compat("Save ZTILE(.ztile)", "ztile", NULL,datapath,false))
9146 break;
9147 PACKFILE *f=pack_fopen_password(temppath,F_WRITE, "");
9148 if(!f) break;
9149 al_trace("Saving tile: %d\n", tile);
9150 writetilefile(f,tile,1);
9151 pack_fclose(f);
9152 break;
9153 }
9154 case KEY_L:
9155 {
9156 if(!prompt_for_existing_file_compat("Load ZTILE(.ztile)", "ztile", NULL,datapath,false))
9157 break;
9158 PACKFILE *f=pack_fopen_password(temppath,F_READ, "");
9159 if(!f) break;
9160 al_trace("Saving tile: %d\n", tile);
9161 if (!readtilefile(f))
9162 {
9163 al_trace("Could not read from .ztile packfile %s\n", temppath);
9164 jwin_alert("ZTILE File: Error","Could not load the specified Tile.",NULL,NULL,"O&K",NULL,'k',0,get_zc_font(font_lfont));
9165 }
9166 else
9167 {
9168 jwin_alert("ZTILE File: Success!","Loaded the source tiles to your tile sheets!",NULL,NULL,"O&K",NULL,'k',0,get_zc_font(font_lfont));
9169 }
9170
9171 pack_fclose(f);
9172 //register_blank_tiles();
9173 //register_used_tiles();
9174 redraw=true;
9175 break;
9176 }
9177 case KEY_MINUS:
9178 case KEY_MINUS_PAD:
9179 {
9180 if(CHECK_CTRL_CMD ||
9181 key[KEY_ALT] || key[KEY_ALTGR])
9182 {
9183 FOREACH_START(t)
9184 if(key[KEY_ALT] || key[KEY_ALTGR])
9185 shift_tile_colors(t, -16, false);
9186 else
9187 shift_tile_colors(t, -1, key[KEY_LSHIFT] || key[KEY_RSHIFT]);
9188 FOREACH_END
9189
9190 register_blank_tiles();
9191 }
9192 else if(edit_cs)
9193 cs = (cs>0) ? cs-1:13;
9194
9195 redraw=true;
9196 break;
9197 }
9198
9199 case KEY_UP:
9200 {
9201 switch(((key[KEY_ALT] || key[KEY_ALTGR])?2:0)+((CHECK_CTRL_CMD)?1:0))
9202 {
9203 case 3: //ALT and CTRL
9204 case 2: //ALT
9205 if(is_rect)
9206 {
9207 saved=false;
9208 go_slide_tiles(columns, rows, top, left);
9209 int32_t bitcheck = newtilebuf[((top)*TILES_PER_ROW)+left].format;
9210 bool same = true;
9211
9212 for(int32_t d=0; d<columns; d++)
9213 {
9214 for(int32_t s=0; s<rows; s++)
9215 {
9216 int32_t t=((top+s)*TILES_PER_ROW)+left+d;
9217
9218 if(newtilebuf[t].format!=bitcheck) same = false;
9219 }
9220 }
9221
9222 if(!same) break;
9223
9224 // This used to do something. Too lazy to remove.
9225 // Can probably remove the above "same" check too.
9226 bitcheck = 2;
9227
9228 for(int32_t c=0; c<columns; c++)
9229 {
9230 for(int32_t r=0; r<rows; r++)
9231 {
9232 int32_t temptile=((top+r)*TILES_PER_ROW)+left+c;
9233 qword *src_pixelrow=(qword*)(newundotilebuf[temptile].data+(8*bitcheck));
9234 qword *dest_pixelrow=(qword*)(newtilebuf[temptile].data);
9235
9236 for(int32_t pixelrow=0; pixelrow<16*bitcheck; pixelrow++)
9237 {
9238 if(pixelrow==15*bitcheck)
9239 {
9240 int32_t srctile=temptile+TILES_PER_ROW;
9241 if(srctile>=NEWMAXTILES)
9242 srctile-=rows*TILES_PER_ROW;
9243 src_pixelrow=(qword*)(newtilebuf[srctile].data);
9244 }
9245
9246 *dest_pixelrow=*src_pixelrow;
9247 dest_pixelrow++;
9248 src_pixelrow++;
9249 }
9250 }
9251
9252 qword *dest_pixelrow=(qword*)(newtilebuf[((top+rows-1)*TILES_PER_ROW)+left+c].data+(120*bitcheck));
9253
9254 for(int32_t b=0; b<bitcheck; b++,dest_pixelrow++)
9255 {
9256 if((CHECK_CTRL_CMD))
9257 {
9258 *dest_pixelrow=0;
9259 }
9260 else
9261 {
9262 qword *src_pixelrow=(qword*)(newundotilebuf[(top*TILES_PER_ROW)+left+c].data+(8*b));
9263 *dest_pixelrow=*src_pixelrow;
9264 }
9265 }
9266 }
9267 }
9268
9269 register_blank_tiles();
9270 redraw=true;
9271 break;
9272
9273 case 1: //CTRL
9274 case 0: //None
9275 sel_tile(tile,tile2,first,type,(CHECK_CTRL_CMD)?-1*(tile_page_row(tile)*TILES_PER_ROW):-TILES_PER_ROW);
9276 redraw=true;
9277
9278 default: //Others
9279 break;
9280 }
9281 }
9282 break;
9283
9284 case KEY_DOWN:
9285 {
9286 switch(((key[KEY_ALT] || key[KEY_ALTGR])?2:0)+((CHECK_CTRL_CMD)?1:0))
9287 {
9288 case 3: //ALT and CTRL
9289 case 2: //ALT
9290 if(is_rect)
9291 {
9292 saved=false;
9293 go_slide_tiles(columns, rows, top, left);
9294 int32_t bitcheck = newtilebuf[((top)*TILES_PER_ROW)+left].format;
9295 bool same = true;
9296
9297 for(int32_t c=0; c<columns; c++)
9298 {
9299 for(int32_t r=0; r<rows; r++)
9300 {
9301 int32_t t=((top+r)*TILES_PER_ROW)+left+c;
9302
9303 if(newtilebuf[t].format!=bitcheck) same = false;
9304 }
9305 }
9306
9307 if(!same) break;
9308
9309 // This used to do something. Too lazy to remove.
9310 // Can probably remove the above "same" check too.
9311 bitcheck = 2;
9312
9313 for(int32_t c=0; c<columns; c++)
9314 {
9315 for(int32_t r=rows-1; r>=0; r--)
9316 {
9317 int32_t temptile=((top+r)*TILES_PER_ROW)+left+c;
9318 qword *src_pixelrow=(qword*)(newundotilebuf[temptile].data+(112*bitcheck)+(8*(bitcheck-1)));
9319 qword *dest_pixelrow=(qword*)(newtilebuf[temptile].data+(120*bitcheck)+(8*(bitcheck-1)));
9320
9321 for(int32_t pixelrow=(8<<bitcheck)-1; pixelrow>=0; pixelrow--)
9322 {
9323 if(pixelrow<bitcheck)
9324 {
9325 int32_t srctile=temptile-TILES_PER_ROW;
9326 if(srctile<0)
9327 srctile+=rows*TILES_PER_ROW;
9328 qword *tempsrc=(qword*)(newtilebuf[srctile].data+(120*bitcheck)+(8*pixelrow));
9329 *dest_pixelrow=*tempsrc;
9330 //*dest_pixelrow=0;
9331 }
9332 else
9333 {
9334 *dest_pixelrow=*src_pixelrow;
9335 }
9336
9337 dest_pixelrow--;
9338 src_pixelrow--;
9339 }
9340 }
9341
9342 qword *dest_pixelrow=(qword*)(newtilebuf[(top*TILES_PER_ROW)+left+c].data);
9343 qword *src_pixelrow=(qword*)(newundotilebuf[((top+rows-1)*TILES_PER_ROW)+left+c].data+(120*bitcheck));
9344
9345 for(int32_t b=0; b<bitcheck; b++)
9346 {
9347 if((CHECK_CTRL_CMD))
9348 {
9349 *dest_pixelrow=0;
9350 }
9351 else
9352 {
9353 *dest_pixelrow=*src_pixelrow;
9354 }
9355
9356 dest_pixelrow++;
9357 src_pixelrow++;
9358 }
9359 }
9360 }
9361
9362 register_blank_tiles();
9363 redraw=true;
9364 break;
9365
9366 case 1: //CTRL
9367 case 0: //None
9368 sel_tile(tile,tile2,first,type,(CHECK_CTRL_CMD)?((TILE_ROWS_PER_PAGE-1)-tile_page_row(tile))*TILES_PER_ROW:TILES_PER_ROW);
9369 redraw=true;
9370
9371 default: //Others
9372 break;
9373 }
9374 }
9375 break;
9376
9377 case KEY_LEFT:
9378 {
9379 switch(((key[KEY_ALT] || key[KEY_ALTGR])?2:0)+((CHECK_CTRL_CMD)?1:0))
9380 {
9381 case 3: //ALT and CTRL
9382 case 2: //ALT
9383 if(is_rect)
9384 {
9385 saved=false;
9386 go_slide_tiles(columns, rows, top, left);
9387 int32_t bitcheck = newtilebuf[((top)*TILES_PER_ROW)+left].format;
9388 bool same = true;
9389
9390 for(int32_t c=0; c<columns; c++)
9391 {
9392 for(int32_t r=0; r<rows; r++)
9393 {
9394 int32_t t=((top+r)*TILES_PER_ROW)+left+c;
9395
9396 if(newtilebuf[t].format!=bitcheck) same = false;
9397 }
9398 }
9399
9400 if(!same) break;
9401
9402 // This used to do something. Too lazy to remove.
9403 // Can probably remove the above "same" check too.
9404 bitcheck = 2;
9405
9406 for(int32_t r=0; r<rows; r++)
9407 {
9408 for(int32_t c=0; c<columns; c++)
9409 {
9410 int32_t temptile=((top+r)*TILES_PER_ROW)+left+c;
9411 byte *dest_pixelrow=(newtilebuf[temptile].data);
9412
9413 for(int32_t pixelrow=0; pixelrow<16; pixelrow++)
9414 {
9415 for(int32_t p=0; p<(8*bitcheck)-1; p++)
9416 {
9417 *dest_pixelrow=*(dest_pixelrow+1);
9418 dest_pixelrow++;
9419 }
9420
9421 if(c==columns-1)
9422 {
9423 if(!(CHECK_CTRL_CMD))
9424 {
9425 byte *tempsrc=(newundotilebuf[((top+r)*TILES_PER_ROW)+left].data+(pixelrow*8*bitcheck));
9426 *dest_pixelrow=*tempsrc;
9427 }
9428 }
9429 else
9430
9431 {
9432 byte *tempsrc=(newtilebuf[temptile+1].data+(pixelrow*8*bitcheck));
9433 *dest_pixelrow=*tempsrc;
9434 }
9435
9436 dest_pixelrow++;
9437 }
9438 }
9439 }
9440
9441 register_blank_tiles();
9442 redraw=true;
9443 }
9444
9445 break;
9446
9447 case 1: //CTRL
9448 case 0: //None
9449 sel_tile(tile,tile2,first,type,(CHECK_CTRL_CMD)?-(tile%TILES_PER_ROW):-1);
9450 redraw=true;
9451
9452 default: //Others
9453 break;
9454 }
9455 }
9456 break;
9457
9458 case KEY_RIGHT:
9459 {
9460 switch(((key[KEY_ALT] || key[KEY_ALTGR])?2:0)+((CHECK_CTRL_CMD)?1:0))
9461 {
9462 case 3: //ALT and CTRL
9463 case 2: //ALT
9464 if(is_rect)
9465 {
9466 saved=false;
9467 go_slide_tiles(columns, rows, top, left);
9468 int32_t bitcheck = newtilebuf[((top)*TILES_PER_ROW)+left].format;
9469 bool same = true;
9470
9471 for(int32_t c=0; c<columns; c++)
9472 {
9473 for(int32_t r=0; r<rows; r++)
9474 {
9475 int32_t t=((top+r)*TILES_PER_ROW)+left+c;
9476
9477 if(newtilebuf[t].format!=bitcheck) same = false;
9478 }
9479 }
9480
9481 if(!same) break;
9482
9483 // This used to do something. Too lazy to remove.
9484 // Can probably remove the above "same" check too.
9485 bitcheck = 2;
9486
9487 for(int32_t r=0; r<rows; r++)
9488 {
9489 for(int32_t c=columns-1; c>=0; c--)
9490 {
9491 int32_t temptile=((top+r)*TILES_PER_ROW)+left+c;
9492 byte *dest_pixelrow=(newtilebuf[temptile].data)+(128*bitcheck)-1;
9493
9494 for(int32_t pixelrow=15; pixelrow>=0; pixelrow--)
9495 {
9496 for(int32_t p=0; p<(8*bitcheck)-1; p++)
9497 {
9498 *dest_pixelrow=*(dest_pixelrow-1);
9499 dest_pixelrow--;
9500 }
9501
9502 if(c==0)
9503 {
9504 if(!(CHECK_CTRL_CMD))
9505 {
9506 byte *tempsrc=(newundotilebuf[(((top+r)*TILES_PER_ROW)+left+columns-1)].data+(pixelrow*8*bitcheck)+(8*bitcheck)-1);
9507 *dest_pixelrow=*tempsrc;
9508 }
9509 }
9510 else
9511 {
9512 byte *tempsrc=(newtilebuf[temptile-1].data+(pixelrow*8*bitcheck)+(8*bitcheck)-1);
9513 *dest_pixelrow=*tempsrc;
9514 }
9515
9516 dest_pixelrow--;
9517 }
9518 }
9519 }
9520
9521 register_blank_tiles();
9522 redraw=true;
9523 }
9524
9525 break;
9526
9527 case 1: //CTRL
9528 case 0: //None
9529 sel_tile(tile,tile2,first,type,(CHECK_CTRL_CMD)?(TILES_PER_ROW)-(tile%TILES_PER_ROW)-1:1);
9530 redraw=true;
9531
9532 default: //Others
9533 break;
9534 }
9535 }
9536 break;
9537
9538 case KEY_PGUP:
9539 sel_tile(tile,tile2,first,type,(CHECK_CTRL_CMD)?-1*(TILEROW(tile)*TILES_PER_ROW):-TILES_PER_PAGE);
9540 redraw=true;
9541 break;
9542
9543 case KEY_PGDN:
9544 sel_tile(tile,tile2,first,type,(CHECK_CTRL_CMD)?((TILE_PAGES*TILE_ROWS_PER_PAGE)-TILEROW(tile)-1)*TILES_PER_ROW:TILES_PER_PAGE);
9545 redraw=true;
9546 break;
9547
9548 case KEY_HOME:
9549 sel_tile(tile,tile2,first,type,(CHECK_CTRL_CMD)?-(tile):-(tile%TILES_PER_PAGE));
9550 redraw=true;
9551 break;
9552
9553 case KEY_END:
9554 sel_tile(tile,tile2,first,type,(CHECK_CTRL_CMD)?(TILE_PAGES)*(TILES_PER_PAGE)-tile-1:(TILES_PER_PAGE)-(tile%TILES_PER_PAGE)-1);
9555 redraw=true;
9556 break;
9557
9558 case KEY_P:
9559 {
9560 int32_t whatPage = gettilepagenumber("Goto Page", (PreFillTileEditorPage?(first/TILES_PER_PAGE):0));
9561
9562 if(whatPage >= 0)
9563 sel_tile(tile,tile2,first,type,((whatPage-TILEPAGE(tile))*TILE_ROWS_PER_PAGE)*TILES_PER_ROW);
9564
9565 break;
9566 }
9567
9568 case KEY_O:
9569 if(type==0 && copy>=0)
9570 {
9571 go_tiles();
9572
9573 if(key[KEY_LSHIFT] ||key[KEY_RSHIFT])
9574 {
9575 mass_overlay_tile(zc_min(tile,tile2),zc_max(tile,tile2),copy,cs,(CHECK_CTRL_CMD), rect_sel);
9576 saved=false;
9577 }
9578 else
9579 {
9580 saved = !overlay_tiles(tile,tile2,copy,copycnt,rect_sel,false,cs,(CHECK_CTRL_CMD));
9581 //overlay_tile(newtilebuf,tile,copy,cs,(CHECK_CTRL_CMD));
9582 }
9583
9584 saved=false;
9585 redraw=true;
9586 }
9587
9588 break;
9589
9590 case KEY_E:
9591 if(type==0)
9592 {
9593 edit_tile(tile,flip,cs);
9594 draw_tile_list_window();
9595 redraw=true;
9596 }
9597
9598 break;
9599
9600 case KEY_G:
9601 if(type==0)
9602 {
9603 grab_tile(tile,cs);
9604 draw_tile_list_window();
9605 redraw=true;
9606 }
9607
9608 break;
9609
9610 case KEY_C:
9611 copy=zc_min(tile,tile2);
9612 copycnt=abs(tile-tile2)+1;
9613 redraw=true;
9614 break;
9615
9616 case KEY_X:
9617 if(type==2)
9618 {
9619 ex=(ex+1)%3;
9620 }
9621
9622 break;
9623
9624 //usetiles=true;
9625 case KEY_R:
9626 if(type==2)
9627 break;
9628 if(type==1)
9629 {
9630 flip = rotate_value(flip);
9631 redraw=true;
9632 break;
9633 }
9634
9635 go_tiles();
9636
9637 if(CHECK_CTRL_CMD)
9638 {
9639 bool go=false;
9640 if(key[KEY_LSHIFT] || key[KEY_RSHIFT])
9641 go=true;
9642 else if(massRecolorSetup(cs))
9643 go=true;
9644
9645 if(go)
9646 {
9647 FOREACH_START(t)
9648 massRecolorApply(t);
9649 FOREACH_END
9650
9651 register_blank_tiles();
9652 }
9653 }
9654 else
9655 {
9656 FOREACH_START(t)
9657 rotate_tile(t,(key[KEY_LSHIFT] || key[KEY_RSHIFT]));
9658 FOREACH_END
9659 }
9660
9661 redraw=true;
9662 saved=false;
9663 break;
9664
9665 case KEY_SPACE:
9666 rect_sel=!rect_sel;
9667 copy=-1;
9668 redraw=true;
9669 break;
9670
9671 // case KEY_N: go_tiles(); normalize(tile,tile2,flip); flip=0; redraw=true; saved=false; usetiles=true; break;
9672 case KEY_H:
9673 flip^=1;
9674 go_tiles();
9675
9676 if(type==0)
9677 {
9678 normalize(tile,tile2,rect_sel,flip);
9679 flip=0;
9680 }
9681
9682 redraw=true;
9683 break;
9684
9685
9686 case KEY_V:
9687 if(copy==-1)
9688 {
9689 if(type!=2)
9690 {
9691 flip^=2;
9692 go_tiles();
9693
9694 if(type==0)
9695 {
9696 normalize(tile,tile2,rect_sel,flip);
9697 flip=0;
9698 }
9699 }
9700 }
9701 else
9702 {
9703 bool alt=(key[KEY_ALT] || key[KEY_ALTGR]);
9704 go_tiles();
9705 saved = !copy_tiles(tile,tile2,copy,copycnt,rect_sel,false);
9706 }
9707
9708 redraw=true;
9709 break;
9710
9711 case KEY_F:
9712 if(copy==-1)
9713 {
9714 break;
9715 }
9716 else
9717 {
9718 go_tiles();
9719 {
9720 saved = !copy_tiles_floodfill(tile,tile2,copy,copycnt,rect_sel,false);
9721 }
9722 }
9723
9724 redraw=true;
9725 break;
9726
9727 case KEY_DEL:
9728 if(type==0 && (key[KEY_LSHIFT]||key[KEY_RSHIFT]))
9729 {
9730 bool warn = (rect_sel
9731 && ((tile/20)!=(tile2/20))
9732 && !(tile%20==0&&tile2%20==19));
9733 int32_t z=zc_min(tile,tile2);
9734 int32_t count = abs(tile-tile2) + 1;
9735 tile=z;
9736 tile2=NEWMAXTILES;
9737 copy = tile + count;
9738 copycnt = NEWMAXTILES-copy;
9739 char buf[64];
9740
9741 if(count>1)
9742 sprintf(buf,"Remove tiles %d - %d?",tile, copy-1);
9743 else
9744 sprintf(buf,"Remove tile %d?",tile);
9745
9746 AlertDialog("Remove Tiles", std::string(buf)
9747 +"\nThis will offset the tiles that follow!"
9748 +(warn?"\nRemoving tiles ignores rectangular selections!":""),
9749 [&](bool ret,bool)
9750 {
9751 if(ret)
9752 {
9753 go_tiles();
9754 if(copy_tiles(tile,tile2,copy,copycnt,false,true))
9755 {
9756 redraw=true;
9757 saved=false;
9758 }
9759 }
9760 }).show();
9761 }
9762 delete_tiles(tile,tile2,rect_sel);
9763 redraw=true;
9764 break;
9765
9766 case KEY_U:
9767 {
9768 if(CHECK_CTRL_CMD)
9769 {
9770 //Only toggle the first 2 bits!
9771 show_only_unused_tiles = (show_only_unused_tiles&~3) | (((show_only_unused_tiles&3)+1)%4);
9772 }
9773 else
9774 {
9775 comeback_tiles();
9776 }
9777
9778 redraw=true;
9779 }
9780 break;
9781
9782 case KEY_8:
9783 case KEY_8_PAD:
9784 hide_8bit_marker();
9785 break;
9786
9787 case KEY_I: //insert tiles
9788 if(type==0)
9789 {
9790 bool warn = (rect_sel
9791 && ((tile/20)!=(tile2/20))
9792 && !(tile%20==0&&tile2%20==19));
9793 int32_t z=zc_min(tile,tile2);
9794 int32_t count = abs(tile-tile2) + 1;
9795 tile=z;
9796 tile2=NEWMAXTILES;
9797 copy = tile + count;
9798 copycnt = NEWMAXTILES-copy;
9799
9800 if(key[KEY_LSHIFT]||key[KEY_RSHIFT]) //Remove
9801 {
9802 char buf[64];
9803
9804 if(count>1)
9805 sprintf(buf,"Remove tiles %d - %d?",tile, copy-1);
9806 else
9807 sprintf(buf,"Remove tile %d?",tile);
9808
9809 AlertDialog("Remove Tiles", std::string(buf)
9810 +"\nThis will offset the tiles that follow!"
9811 +(warn?"\nRemoving tiles ignores rectangular selections!":""),
9812 [&](bool ret,bool)
9813 {
9814 if(ret)
9815 {
9816 go_tiles();
9817 if(copy_tiles(tile,tile2,copy,copycnt,false,true))
9818 {
9819 redraw=true;
9820 saved=false;
9821 }
9822 }
9823 }).show();
9824 }
9825 else
9826 {
9827 char buf[64];
9828
9829 if(count>1)
9830 sprintf(buf,"Insert %d blank tiles?",count);
9831 else
9832 sprintf(buf,"Insert a blank tile?");
9833
9834 AlertDialog("Insert Tiles", std::string(buf)
9835 +"\nThis will offset the tiles that follow!"
9836 +(warn?"\nInserting tiles ignores rectangular selections!":""),
9837 [&](bool ret,bool)
9838 {
9839 if(ret)
9840 {
9841 go_tiles();
9842 if(copy_tiles(copy,tile2,tile,copycnt,false,true))
9843 {
9844 redraw=true;
9845 saved=false;
9846 }
9847 }
9848 }).show();
9849 }
9850
9851 copy=-1;
9852 tile2=tile=z;
9853 }
9854 break;
9855 case KEY_M:
9856 if(type==0)
9857 {
9858 if((copy!=-1)&&(copy!=zc_min(tile,tile2)))
9859 {
9860 go_tiles();
9861 if(copy_tiles(tile,tile2,copy,copycnt,rect_sel,true))
9862 saved=false;
9863 }
9864 else if(copy==-1)
9865 {
9866 // I don't know what this was supposed to be doing before.
9867 // It didn't work in anything like a sensible way.
9868 if(rect_sel)
9869 {
9870 make_combos_rect(top, left, rows, columns, cs);
9871 }
9872 else
9873 {
9874 make_combos(zc_min(tile, tile2), zc_max(tile, tile2), cs);
9875 }
9876 }
9877
9878 redraw=true;
9879 }
9880 break;
9881
9882 case KEY_D:
9883 {
9884 int32_t frames=1;
9885 char buf[80];
9886 sprintf(buf, "%d", frames);
9887 create_relational_tiles_dlg[0].dp2=get_zc_font(font_lfont);
9888 create_relational_tiles_dlg[2].dp=buf;
9889
9890 large_dialog(create_relational_tiles_dlg);
9891
9892 int32_t ret=do_zqdialog(create_relational_tiles_dlg,2);
9893
9894 if(ret==5)
9895 {
9896 frames=zc_max(atoi(buf),1);
9897 bool same = true;
9898 int32_t bitcheck=newtilebuf[tile].format;
9899
9900 for(int32_t t=1; t<frames*(create_relational_tiles_dlg[3].flags&D_SELECTED?6:19); ++t)
9901 {
9902 if(newtilebuf[tile+t].format!=bitcheck) same = false;
9903 }
9904
9905 if(!same)
9906 {
9907 jwin_alert("Error","The source tiles are not","in the same format.",NULL,"&OK",NULL,13,27,get_zc_font(font_lfont));
9908 break;
9909 }
9910
9911 if(tile+(frames*(create_relational_tiles_dlg[3].flags&D_SELECTED?48:96))>NEWMAXTILES)
9912 {
9913 jwin_alert("Error","Too many tiles will be created",NULL,NULL,"&OK",NULL,13,27,get_zc_font(font_lfont));
9914 break;
9915 }
9916
9917 for(int32_t i=frames*(create_relational_tiles_dlg[3].flags&D_SELECTED?6:19); i<(frames*(create_relational_tiles_dlg[3].flags&D_SELECTED?48:96)); ++i)
9918 {
9919 reset_tile(newtilebuf, tile+i, bitcheck);
9920 }
9921
9922 if(create_relational_tiles_dlg[3].flags&D_SELECTED)
9923 {
9924 for(int32_t i=create_relational_tiles_dlg[3].flags&D_SELECTED?47:95; i>0; --i)
9925 {
9926 for(int32_t j=0; j<frames; ++j)
9927 {
9928 merge_tiles(tile+(i*frames)+j, (tile+(relational_template[i][0]*frames)+j)<<2, ((tile+(relational_template[i][1]*frames)+j)<<2)+1, ((tile+(relational_template[i][2]*frames)+j)<<2)+2, ((tile+(relational_template[i][3]*frames)+j)<<2)+3);
9929 }
9930 }
9931 }
9932 else
9933 {
9934 for(int32_t i=create_relational_tiles_dlg[3].flags&D_SELECTED?47:95; i>0; --i)
9935 {
9936 for(int32_t j=0; j<frames; ++j)
9937 {
9938 merge_tiles(tile+(i*frames)+j, (tile+(dungeon_carving_template[i][0]*frames)+j)<<2, ((tile+(dungeon_carving_template[i][1]*frames)+j)<<2)+1, ((tile+(dungeon_carving_template[i][2]*frames)+j)<<2)+2, ((tile+(dungeon_carving_template[i][3]*frames)+j)<<2)+3);
9939 }
9940 }
9941 }
9942 }
9943 register_blank_tiles();
9944 register_used_tiles();
9945 redraw=true;
9946 saved=false;
9947 break;
9948 }
9949
9950 case KEY_B:
9951 {
9952 bool shift=(key[KEY_LSHIFT] || key[KEY_RSHIFT]);
9953 bool control=(CHECK_CTRL_CMD);
9954 bool alt=(key[KEY_ALT] || key[KEY_ALTGR]);
9955 int format = control ? tf4Bit : tf8Bit;
9956
9957 do_convert_tile(tile, tile2, cs, rect_sel, format, shift, alt);
9958 register_blank_tiles();
9959 }
9960 break;
9961 }
9962
9963 clear_keybuf();
9964 }
9965
9966 if(!(key[KEY_Z] || key[KEY_F12]))
9967 did_snap = false;
9968
9969 if(gui_mouse_b()&1)
9970 {
9971 if(isinRect(gui_mouse_x(),gui_mouse_y(),window_xofs + w + 12 - 21, window_yofs + 5, window_xofs + w +12 - 21 + 15, window_yofs + 5 + 13))
9972 {
9973 if(do_x_button(screen, w+12+window_xofs - 21, 5+window_yofs))
9974 {
9975 done=1;
9976 }
9977 }
9978
9979 int32_t x=gui_mouse_x()-screen_xofs;
9980 int32_t y=gui_mouse_y()-screen_yofs;
9981
9982 if(y>=0 && y<208*mul)
9983 {
9984 x=zc_min(zc_max(x,0),(320*mul)-1);
9985 int32_t t = (y>>(5))*TILES_PER_ROW + (x>>(5)) + first;
9986
9987 if(type==0 && (key[KEY_LSHIFT] || key[KEY_RSHIFT]))
9988 {
9989 tile2=t;
9990 }
9991 else
9992 {
9993 tile=tile2=t;
9994 }
9995
9996 if(tile_clicked!=t)
9997 {
9998 dclick_status=DCLICK_NOT;
9999 }
10000 else if(dclick_status == DCLICK_AGAIN)
10001 {
10002 while(gui_mouse_b())
10003 {
10004 /* do nothing */
10005 rest(1);
10006 }
10007
10008 if(((y>>(5))*TILES_PER_ROW + (x>>(5)) + first)!=t)
10009 {
10010 dclick_status=DCLICK_NOT;
10011 }
10012 else
10013 {
10014 if(type==0)
10015 {
10016 edit_tile(tile,flip,cs);
10017 draw_tile_list_window();
10018 redraw=true;
10019 }
10020 else
10021 {
10022 done=2;
10023 }
10024 }
10025 }
10026
10027 tile_clicked=t;
10028 }
10029 else if(x>300*mul && !bdown)
10030 {
10031 if(y<224*mul && first>0)
10032 {
10033 first-=TILES_PER_PAGE;
10034 redraw=true;
10035 }
10036
10037 if(y>=224*mul && first<TILES_PER_PAGE*(TILE_PAGES-1))
10038 {
10039 first+=TILES_PER_PAGE;
10040 redraw=true;
10041 }
10042
10043 bdown=true;
10044 }
10045
10046 if(type==1||type==2)
10047 {
10048 if(!bdown && isinRect(x,y,8*mul,216*mul+panel_yofs,23*mul,231*mul+panel_yofs))
10049 done=1;
10050
10051 if(!bdown && isinRect(x,y,148*mul,216*mul+panel_yofs,163*mul,231*mul+panel_yofs))
10052 done=2;
10053 }
10054 else if(!bdown && isinRect(x,y,127*mul,216*mul+panel_yofs,(127+15)*mul,(216+15)*mul+panel_yofs))
10055 {
10056 rect_sel=!rect_sel;
10057 copy=-1;
10058 redraw=true;
10059 }
10060 else if(!bdown && isinRect(x,y,150*mul,213*mul+panel_yofs,(150+28)*mul,(213+21)*mul+panel_yofs))
10061 {
10062 FONT *tf = font;
10063 font = tfont;
10064
10065 if(do_text_button(150*mul+screen_xofs,213*mul+screen_yofs+panel_yofs,28*mul,21*mul,"&Grab"))
10066 {
10067 font = tf;
10068 grab_tile(tile,cs);
10069 draw_tile_list_window();
10070 position_mouse_z(0);
10071 redraw=true;
10072 }
10073
10074 font = tf;
10075 }
10076 else if(!bdown && isinRect(x,y,(150+28)*mul,213*mul+panel_yofs,(150+28*2)*mul,(213+21)*mul+panel_yofs+21))
10077 {
10078 FONT *tf = font;
10079 font = tfont;
10080
10081 if(do_text_button((150+28)*mul+screen_xofs,213*mul+screen_yofs+panel_yofs,28*mul,21*mul,"&Edit"))
10082 {
10083 font = tf;
10084 edit_tile(tile,flip,cs);
10085 draw_tile_list_window();
10086 redraw=true;
10087 }
10088
10089 font = tf;
10090 }
10091 else if(!bdown && isinRect(x,y,(150+28*2)*mul,213*mul+panel_yofs,(150+28*3)*mul,(213+21)*mul+panel_yofs))
10092 {
10093 FONT *tf = font;
10094 font = tfont;
10095
10096 if(do_text_button((150+28*2)*mul+screen_xofs,213*mul+screen_yofs+panel_yofs,28*mul,21*mul,"Export"))
10097 {
10098 std::string initial_path = "tileset.png";
10099 if (strlen(datapath))
10100 initial_path = fmt::format("{}/{}", datapath, initial_path);
10101 if(prompt_for_new_file_compat("Export Tile Page (.png)","png",NULL,initial_path,true))
10102 {
10103 PALETTE temppal;
10104 get_palette(temppal);
10105 BITMAP *tempbmp=create_bitmap_ex(8,16*TILES_PER_ROW, 16*TILE_ROWS_PER_PAGE);
10106 draw_tiles(tempbmp,first,cs,f,false,true);
10107 save_bitmap(temppath, tempbmp, RAMpal);
10108 destroy_bitmap(tempbmp);
10109 }
10110 }
10111
10112 font = tf;
10113 }
10114 else if(!bdown && isinRect(x,y,(150+28*3)*mul,213*mul+panel_yofs,(150+28*4)*mul,(213+21)*mul+panel_yofs))
10115 {
10116 FONT *tf = font;
10117 font = tfont;
10118
10119 if(do_text_button((150+28*3)*mul+screen_xofs,213*mul+screen_yofs+panel_yofs,28*mul,21*mul,"Recolor"))
10120 {
10121 if(massRecolorSetup(cs))
10122 {
10123 go_tiles();
10124
10125 FOREACH_START(t)
10126 massRecolorApply(t);
10127 FOREACH_END
10128
10129 register_blank_tiles();
10130 }
10131 }
10132
10133 font = tf;
10134 }
10135 else if(!bdown && isinRect(x,y,(150+28*4)*mul,213*mul+panel_yofs,(150+28*5)*mul,(213+21)*mul+panel_yofs))
10136 {
10137 FONT *tf = font;
10138 font = tfont;
10139
10140 if(do_text_button((150+28*4)*mul+screen_xofs,213*mul+screen_yofs+panel_yofs,28*mul,21*mul,"Done"))
10141 {
10142 done=1;
10143 }
10144
10145 font = tf;
10146 }
10147
10148 bdown=true;
10149 }
10150
10151 bool r_click = false;
10152
10153 if(gui_mouse_b()&2 && !bdown && type==0)
10154 {
10155 int32_t x=(gui_mouse_x()-screen_xofs);//&0xFF0;
10156 int32_t y=(gui_mouse_y()-screen_yofs);//&0xF0;
10157
10158 if(y>=0 && y<208*mul)
10159 {
10160 x=zc_min(zc_max(x,0),(320*mul)-1);
10161 int32_t t = ((y)>>(5))*TILES_PER_ROW + ((x)>>(5)) + first;
10162
10163 if(t<zc_min(tile,tile2) || t>zc_max(tile,tile2))
10164 tile=tile2=t;
10165 }
10166
10167 bdown = r_click = true;
10168 f=8;
10169 }
10170
10171 if(gui_mouse_b()==0)
10172 bdown=false;
10173
10174 position_mouse_z(0);
10175
10176 REDRAW:
10177
10178 if((f%8)==0 || InvalidBG == 1)
10179 redraw=true;
10180 if(otl != tile || otl2 != tile2)
10181 {
10182 otl = tile;
10183 otl2 = tile2;
10184 redraw = true;
10185 }
10186
10187 if(redraw)
10188 {
10189 draw_tiles(first,cs,f);
10190 }
10191 if(f&8)
10192 {
10193 if(rect_sel)
10194 {
10195 for(int32_t i=zc_min(TILEROW(tile),TILEROW(tile2))*TILES_PER_ROW+
10196 zc_min(TILECOL(tile),TILECOL(tile2));
10197 i<=zc_max(TILEROW(tile),TILEROW(tile2))*TILES_PER_ROW+
10198 zc_max(TILECOL(tile),TILECOL(tile2)); i++)
10199 {
10200 if(i>=first && i<first+TILES_PER_PAGE &&
10201 TILECOL(i)>=zc_min(TILECOL(tile),TILECOL(tile2)) &&
10202 TILECOL(i)<=zc_max(TILECOL(tile),TILECOL(tile2)))
10203 {
10204 int32_t x=TILECOL(i)<<(5);
10205 int32_t y=TILEROW(i-first)<<(5);
10206 safe_rect(screen2,x,y,x+(16*mul)-1,y+(16*mul)-1,vc(TilePgCursorCol),2);
10207 }
10208 }
10209 }
10210 else
10211 {
10212 for(int32_t i=zc_min(tile,tile2); i<=zc_max(tile,tile2); i++)
10213 {
10214 if(i>=first && i<first+TILES_PER_PAGE)
10215 {
10216 int32_t x=TILECOL(i)<<(5);
10217 int32_t y=TILEROW(i-first)<<(5);
10218 safe_rect(screen2,x,y,x+(16*mul)-1,y+(16*mul)-1,vc(TilePgCursorCol),2);
10219 }
10220 }
10221 }
10222 }
10223
10224 if(type==0)
10225 tile_info_0(tile,tile2,cs,copy,copycnt,first/TILES_PER_PAGE,rect_sel);
10226 else
10227 tile_info_1(otile,oflip,ocs,tile,flip,cs,copy,first/TILES_PER_PAGE, always_use_flip);
10228
10229 if(type==2)
10230 {
10231 char cbuf[16];
10232 sprintf(cbuf, "E&xtend: %s",ex==2 ? "32x32" : ex==1 ? "32x16" : "16x16");
10233 gui_textout_ln(screen, get_zc_font(font_lfont_l), (uint8_t *)cbuf, (235*mul)+screen_xofs, (212*mul)+screen_yofs+panel_yofs, jwin_pal[jcBOXFG],jwin_pal[jcBOX],0);
10234 }
10235
10236 ++f;
10237
10238 if(r_click)
10239 {
10240 select_tile_view_menu.select_uid(MENUID_SELTILE_VIEW_HIDE_USED, HIDE_USED);
10241 select_tile_view_menu.select_uid(MENUID_SELTILE_VIEW_HIDE_UNUSED, HIDE_UNUSED);
10242 select_tile_view_menu.select_uid(MENUID_SELTILE_VIEW_HIDE_BLANK, HIDE_BLANK);
10243 select_tile_view_menu.select_uid(MENUID_SELTILE_VIEW_HIDE_8BIT, HIDE_8BIT_MARKER);
10244
10245 int current_tile_format = MENUID_SELTILE_COLOR_DEPTH_4_BIT;
10246 if (newtilebuf[tile].format == tf8Bit)
10247 current_tile_format = MENUID_SELTILE_COLOR_DEPTH_8_BIT;
10248 select_tile_color_depth_menu.select_only_uid(current_tile_format);
10249 select_tile_color_depth_cb = [&](int format){
10250 if (newtilebuf[tile].format == format)
10251 return;
10252
10253 bool skip_prompt = true;
10254 do_convert_tile(tile, tile2, cs, rect_sel, format, false, false, skip_prompt);
10255 };
10256
10257 NewMenu rcmenu
10258 {
10259 { "Copy", [&]()
10260 {
10261 copy = zc_min(tile,tile2);
10262 copycnt = abs(tile-tile2)+1;
10263 } },
10264 { "Paste", [&]()
10265 {
10266 bool b = copy_tiles(tile, tile2, copy, copycnt, rect_sel, false);
10267 if(saved) saved = !b;
10268 }, nullopt, copy < 0 },
10269 { "Move", [&]()
10270 {
10271 bool b = copy_tiles(tile, tile2, copy, copycnt, rect_sel, true);
10272 if(saved) saved = !b;
10273 }, nullopt, copy < 0 },
10274 { "Clear", [&]()
10275 {
10276 delete_tiles(tile, tile2, rect_sel);
10277 } },
10278 {},
10279 { "Edit", [&]()
10280 {
10281 edit_tile(tile, flip, cs);
10282 draw_tile_list_window();
10283 } },
10284 { "Grab", [&]()
10285 {
10286 grab_tile(tile, cs);
10287 draw_tile_list_window();
10288 position_mouse_z(0);
10289 } },
10290 { "Scale", [&]()
10291 {
10292 bool b = scale_or_rotate_tiles(tile, tile2, cs, false);
10293 if(saved) saved = !b;
10294 }, nullopt, type != 0 },
10295 { "Angular Rotation", [&]()
10296 {
10297 bool b = scale_or_rotate_tiles(tile, tile2, cs, true);
10298 if(saved) saved = !b;
10299 }, nullopt, type != 0 },
10300 { "Color Depth", &select_tile_color_depth_menu },
10301 {},
10302 { "Blank?", [&]()
10303 {
10304 show_blank_tile(tile);
10305 } },
10306 {},
10307 { "View ", &select_tile_view_menu },
10308 { "Overlay", [&]()
10309 {
10310 overlay_tile(newtilebuf, tile, copy, cs, 0);
10311 } },
10312 { "H-Flip", [&]()
10313 {
10314 flip ^= 1;
10315 go_tiles();
10316
10317 if(type == 0)
10318 {
10319 normalize(tile, tile2, rect_sel, flip);
10320 flip = 0;
10321 }
10322 } },
10323 { "V-Flip", [&]()
10324 {
10325 flip ^= 2;
10326 go_tiles();
10327
10328 if(type == 0)
10329 {
10330 normalize(tile, tile2, rect_sel, flip);
10331 flip = 0;
10332 }
10333 } },
10334 { "Create Combos", [&]()
10335 {
10336 if(rect_sel)
10337 make_combos_rect(top, left, rows, columns, cs);
10338 else
10339 make_combos(zc_min(tile, tile2), zc_max(tile, tile2), cs);
10340 }, nullopt, type != 0 },
10341 { "Insert", [&]()
10342 {
10343 bool warn = (rect_sel
10344 && ((tile/20)!=(tile2/20))
10345 && !(tile%20==0&&tile2%20==19));
10346 int32_t z = zc_min(tile, tile2);
10347 int32_t count = abs(tile-tile2) + 1;
10348 tile = z;
10349 tile2 = NEWMAXTILES;
10350 copy = tile + count;
10351 copycnt = NEWMAXTILES-copy;
10352
10353 string msg;
10354
10355 if(count>1)
10356 msg = fmt::format("Insert {} blank tiles?",count);
10357 else
10358 msg = "Insert a blank tile?";
10359
10360 AlertDialog("Insert Tiles", msg
10361 +"\nThis will offset the tiles that follow!"
10362 +(warn?"\nInserting tiles ignores rectangular selections!":""),
10363 [&](bool ret,bool)
10364 {
10365 if(ret)
10366 {
10367 go_tiles();
10368 if(copy_tiles(copy, tile2, tile, copycnt, false, true))
10369 saved = false;
10370 }
10371 }).show();
10372
10373 copy=-1;
10374 tile2=tile=z;
10375 }, nullopt, type != 0 },
10376 { "Remove", [&]()
10377 {
10378 bool warn = (rect_sel
10379 && ((tile/20)!=(tile2/20))
10380 && !(tile%20==0&&tile2%20==19));
10381 int32_t z = zc_min(tile, tile2);
10382 int32_t count = abs(tile-tile2) + 1;
10383 tile = z;
10384 tile2 = NEWMAXTILES;
10385 copy = tile + count;
10386 copycnt = NEWMAXTILES-copy;
10387
10388 string msg;
10389
10390 if(count>1)
10391 msg = fmt::format("Remove tiles {} - {}?", tile, copy-1);
10392 else
10393 msg = fmt::format("Remove tile {}?", tile);
10394
10395 AlertDialog("Remove Tiles", msg
10396 +"\nThis will offset the tiles that follow!"
10397 +(warn?"\nRemoving tiles ignores rectangular selections!":""),
10398 [&](bool ret,bool)
10399 {
10400 if(ret)
10401 {
10402 go_tiles();
10403 if(copy_tiles(tile, tile2, copy, copycnt, false, true))
10404 saved = false;
10405 }
10406 }).show();
10407
10408 copy=-1;
10409 tile2=tile=z;
10410 }, nullopt, type != 0 },
10411 };
10412 rcmenu.pop(window_mouse_x(),window_mouse_y());
10413 redraw = true;
10414 r_click = false;
10415 goto REDRAW;
10416 }
10417 update_hw_screen();
10418 }
10419 while(!done);
10420
10421 while(gui_mouse_b())
10422 {
10423 /* do nothing */
10424 rest(1);
10425 }
10426
10427 comeback();
10428 register_blank_tiles();
10429 register_used_tiles();
10430 setup_combo_animations();
10431 setup_combo_animations2();
10432 int32_t ret = done-1;
10433 if(ret)
10434 {
10435 _selected_tile = tile;
10436 _selected_tcset = cs;
10437 }
10438
10439 popup_zqdialog_end();
10440 return ret;
10441 }
10442 int32_t select_tile_2(int32_t &tile,int32_t &flip,int32_t type,int32_t &cs,bool edit_cs,int32_t exnow, bool always_use_flip)
10443 {
10444 if(_selected_tile > -1)
10445 {
10446 tile = _selected_tile;
10447 cs = _selected_tcset;
10448 }
10449 int32_t ret = select_tile(tile,flip,type,cs,edit_cs,exnow,always_use_flip);
10450 if(_selected_tile < 0)
10451 {
10452 _selected_tile = tile;
10453 _selected_tcset = cs;
10454 }
10455 return ret;
10456 }
10457
10458 int32_t onTiles()
10459 {
10460 return onGotoTiles(-1);
10461 }
10462
10463 int32_t onGotoTiles(int32_t startfrom)
10464 {
10465 static int32_t t = 0;
10466 if (startfrom > -1)
10467 t = startfrom;
10468 int32_t f = 0;
10469 int32_t c = CSet;
10470 reset_pal_cycling();
10471 // loadlvlpal(Map.CurrScr()->color);
10472 rebuild_trans_table();
10473 select_tile(t, f, 0, c, true);
10474 refresh(rALL);
10475 return D_O_K;
10476 }
10477
10478 int32_t combopage_animate = 1;
10479 void draw_combo(BITMAP *dest, int x,int y,int c,int cs,bool animate)
10480 {
10481 if(unsigned(c)<MAXCOMBOS)
10482 {
10483 newcombo& cmb = combobuf[c];
10484 int t = cmb.tile;
10485 if(!animate)
10486 cmb.tile = cmb.o_tile;
10487 put_combo(dest,x,y,c,cs,0,0);
10488 cmb.tile = t;
10489 }
10490 else
10491 {
10492 rectfill(dest,x,y,x+32-1,y+32-1,0);
10493 }
10494 }
10495
10496 void draw_combos(int32_t page,int32_t cs,bool cols)
10497 {
10498 clear_bitmap(screen2);
10499 BITMAP *buf = create_bitmap_ex(8,16,16);
10500
10501 int32_t w = 32;
10502 int32_t h = 32;
10503 int32_t mul = 2;
10504
10505 int32_t window_xofs=(zq_screen_w-640-12)>>1;
10506 int32_t window_yofs=(zq_screen_h-480-25-6)>>1;
10507 int32_t screen_xofs=window_xofs+6;
10508 int32_t screen_yofs=window_yofs+25;
10509
10510 if(cols==false)
10511 {
10512 for(int32_t i=0; i<256; i++) // 13 rows, leaving 32 pixels from y=208 to y=239
10513 {
10514 int32_t x = (i%COMBOS_PER_ROW)*w;
10515 int32_t y = (i/COMBOS_PER_ROW)*h;
10516
10517 combotile_override_x = x+screen_xofs+(w-16)/2;
10518 combotile_override_y = y+screen_yofs+(h-16)/2;
10519 draw_combo(buf,0,0,i+(page<<8),cs,combopage_animate);
10520 stretch_blit(buf,screen2,0,0,16,16,x,y,w,h);
10521 }
10522 }
10523 else
10524 {
10525 int32_t c = 0;
10526
10527 for(int32_t i=0; i<256; i++)
10528 {
10529 int32_t x = (i%COMBOS_PER_ROW)*w;
10530 int32_t y = (i/COMBOS_PER_ROW)*h;
10531
10532 combotile_override_x = x+screen_xofs+(w-16)/2;
10533 combotile_override_y = y+screen_yofs+(h-16)/2;
10534 draw_combo(buf,0,0,c+(page<<8),cs,combopage_animate);
10535 stretch_blit(buf,screen2,0,0,16,16,x,y,w,h);
10536 ++c;
10537
10538 if((i&3)==3)
10539 c+=48;
10540
10541 if((i%COMBOS_PER_ROW)==(COMBOS_PER_ROW-1))
10542 c-=256;
10543 }
10544 }
10545 combotile_override_x = combotile_override_y = -1;
10546
10547 for(int32_t x=(64*mul); x<(320*mul); x+=(64*mul))
10548 {
10549 vline(screen2,x,0,(208*mul)-1,vc(15));
10550 }
10551
10552 destroy_bitmap(buf);
10553 }
10554
10555 void combo_info(int32_t tile,int32_t tile2,int32_t cs,int32_t copy,int32_t copycnt,int32_t page,int32_t buttons)
10556 {
10557 int32_t yofs=3;
10558 static BITMAP *buf = create_bitmap_ex(8,16,16);
10559 int32_t mul = 2;
10560 FONT *tfont = get_zc_font(font_lfont_l);
10561
10562 rectfill(screen2,0,210*2,(320*2)-1,(240*2)-1,jwin_pal[jcBOX]);
10563 hline(screen2, 0, (210*2)-2, (320*2)-1, jwin_pal[jcMEDLT]);
10564 hline(screen2, 0, (210*2)-1, (320*2)-1, jwin_pal[jcLIGHT]);
10565
10566 jwin_draw_frame(screen2,(31*mul)-2,((216*mul)+yofs)-2,(16*mul)+4,(16*mul)+4,FR_DEEP);
10567
10568 if(copy>=0)
10569 {
10570 put_combo(buf,0,0,copy,cs,0,0);
10571 stretch_blit(buf,screen2,0,0,16,16,31*mul,216*mul+yofs,16*mul,16*mul);
10572
10573 if(copycnt>1)
10574 {
10575 textprintf_right_ex(screen2,tfont,28*mul,(216*mul)+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d-",copy);
10576 textprintf_right_ex(screen2,tfont,24*mul,(224*mul)+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d",copy+copycnt-1);
10577 }
10578 else
10579 {
10580 textprintf_right_ex(screen2,tfont,24*mul,(220*mul)+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d",copy);
10581 }
10582 }
10583 else
10584 {
10585 if (InvalidBG == 2)
10586 {
10587 draw_checkerboard(screen2, 31 * mul, 216 * mul + yofs, 16 * mul);
10588 }
10589 else if(InvalidBG == 1)
10590 {
10591 for(int32_t dy=0; dy<16*mul; dy++)
10592 {
10593 for(int32_t dx=0; dx<16*mul; dx++)
10594 {
10595 screen2->line[(216*mul)+yofs+dy][(31*mul)+dx]=vc((((zc_oldrand()%100)/50)?0:8)+(((zc_oldrand()%100)/50)?0:7));
10596 }
10597 }
10598 }
10599 else
10600 {
10601 rectfill(screen2, (31*mul), (216*mul)+yofs, (31*mul)+31, (216*mul)+yofs+31, vc(0));
10602 rect(screen2, (31*mul), (216*mul)+yofs, (31*mul)+31, (216*mul)+yofs+31, vc(15));
10603 line(screen2, (31*mul), (216*mul)+yofs, (31*mul)+31, (216*mul)+yofs+31, vc(15));
10604 line(screen2, (31*mul), (216*mul)+yofs+31, (31*mul)+31, (216*mul)+yofs, vc(15));
10605 }
10606 }
10607
10608 jwin_draw_frame(screen2,(53*mul)-2,(216*mul)+yofs-2,(16*mul)+4,(16*mul)+4,FR_DEEP);
10609 put_combo(buf,0,0,tile,cs,0,0);
10610 stretch_blit(buf,screen2,0,0,16,16,53*mul,216*mul+yofs,16*mul,16*mul);
10611
10612 if(tile>tile2)
10613 {
10614 zc_swap(tile,tile2);
10615 }
10616
10617 char cbuf[8];
10618 cbuf[0]=0;
10619
10620 if(tile2!=tile)
10621 {
10622 sprintf(cbuf,"-%d",tile2);
10623 }
10624
10625 textprintf_ex(screen2,tfont,(73*mul),(216*mul)+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"combo: CSet %d", cs);
10626 textprintf_ex(screen2,tfont,(73*mul),(224*mul)+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d%s",tile,cbuf);
10627
10628 if(tile2==tile)
10629 {
10630 int32_t nextcombo=combobuf[tile].nextcombo;
10631 int32_t nextcset=(combobuf[tile].animflags & AF_CYCLENOCSET) ? cs : combobuf[tile].nextcset;
10632 jwin_draw_frame(screen2,(136*mul)-2,(216*mul)+yofs-2,(16*mul)+4,(16*mul)+4,FR_DEEP);
10633
10634 if(nextcombo>0)
10635 {
10636 put_combo(buf,0,0,nextcombo,nextcset,0,0);
10637 stretch_blit(buf,screen2,0,0,16,16,136*mul,216*mul+yofs,16*mul,16*mul);
10638 }
10639 else
10640 {
10641 if (InvalidBG == 2)
10642 {
10643 draw_checkerboard(screen2, 136 * mul, 216 * mul + yofs, 16 * mul);
10644 }
10645 else if(InvalidBG == 1)
10646 {
10647 for(int32_t dy=0; dy<16*mul; dy++)
10648 {
10649 for(int32_t dx=0; dx<16*mul; dx++)
10650 {
10651 screen2->line[(216*mul)+yofs+dy][(136*mul)+dx]=vc((((zc_oldrand()%100)/50)?0:8)+(((zc_oldrand()%100)/50)?0:7));
10652 }
10653 }
10654 }
10655 else
10656 {
10657 rectfill(screen2, (136*mul), (216*mul)+yofs, (136*mul)+31, (216*mul)+yofs+31, vc(0));
10658 rect(screen2, (136*mul), (216*mul)+yofs, (136*mul)+31, (216*mul)+yofs+31, vc(15));
10659 line(screen2, (136*mul), (216*mul)+yofs, (136*mul)+31, (216*mul)+yofs+31, vc(15));
10660 line(screen2, (136*mul), (216*mul)+yofs+31, (136*mul)+31, (216*mul)+yofs, vc(15));
10661 }
10662 }
10663
10664 textprintf_right_ex(screen2,tfont,(132*mul),(216*mul)+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"Cycle:");
10665 textprintf_right_ex(screen2,tfont,(132*mul),(224*mul)+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d",nextcombo);
10666 }
10667
10668
10669 FONT *tf = font;
10670 font = tfont;
10671
10672 draw_checkbox(screen2,320,440+yofs,16,combopage_animate);
10673 textprintf_ex(screen2,tfont,320+18,440+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"Animate");
10674
10675 if(buttons&2)
10676 {
10677 draw_text_button(screen2,404,426+yofs,88,42,"Edit",jwin_pal[jcBOXFG],jwin_pal[jcBOX],0,true);
10678 }
10679
10680 if(buttons&4)
10681 {
10682 draw_text_button(screen2,494,426+yofs,88,42,"Done",jwin_pal[jcBOXFG],jwin_pal[jcBOX],0,true);
10683 }
10684
10685 font = tf;
10686
10687 jwin_draw_icon(screen2,(305*mul+4),220*mul-6+yofs,jwin_pal[jcBOXFG],BTNICON_ARROW_UP,6,true);
10688 textprintf_ex(screen2,tfont,(293*mul),(220*mul)+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"p:");
10689 textprintf_centre_ex(screen2,tfont,(309*mul),(220*mul)+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d",page);
10690 jwin_draw_icon(screen2,(305*mul+4),228*mul+3+yofs,jwin_pal[jcBOXFG],BTNICON_ARROW_DOWN,6,true);
10691
10692 int32_t w = 640;
10693 int32_t h = 480;
10694 int32_t window_xofs=(zq_screen_w-w-12)>>1;
10695 int32_t window_yofs=(zq_screen_h-h-25-6)>>1;
10696 int32_t screen_xofs=window_xofs+6;
10697 int32_t screen_yofs=window_yofs+25;
10698
10699 custom_vsync();
10700 blit(screen2,screen,0,0,screen_xofs,screen_yofs,w,h);
10701 SCRFIX();
10702 //destroy_bitmap(buf);
10703 }
10704
10705 void sel_combo(int32_t &tile, int32_t &tile2, int32_t s, bool cols)
10706 {
10707 int32_t page = tile&0xFF00;
10708 tile &= 0xFF;
10709
10710 if(!cols)
10711 tile += s;
10712 else
10713 {
10714 if(s==-COMBOS_PER_ROW)
10715 tile-=4;
10716
10717 if(s==COMBOS_PER_ROW)
10718 tile+=4;
10719
10720 if(s==-1)
10721 tile-=1;
10722
10723 if(s==1)
10724 tile+=1;
10725 }
10726
10727 /*
10728 if(s==1)
10729 {
10730 if((tile&3)==3)
10731 tile+=48;
10732 else
10733 ++tile;
10734 }
10735 if(s==-1)
10736 {
10737 if((tile&3)==0)
10738 tile-=48;
10739 else
10740 --tile;
10741 }
10742 }
10743 */
10744 bound(tile,0,255);
10745 tile += page;
10746
10747 if(!(key[KEY_LSHIFT] || key[KEY_RSHIFT]))
10748 tile2 = tile;
10749 }
10750
10751 void draw_combo_list_window()
10752 {
10753 int32_t window_xofs=0;
10754 int32_t window_yofs=0;
10755 int32_t w = 640;
10756 int32_t h = 480;
10757
10758 window_xofs=(zq_screen_w-w-12)>>1;
10759 window_yofs=(zq_screen_h-h-25-6)>>1;
10760 jwin_draw_win(screen, window_xofs, window_yofs, w+6+6, h+25+6, FR_WIN);
10761 jwin_draw_frame(screen, window_xofs+4, window_yofs+23, w+2+2, h+4+2-64, FR_DEEP);
10762 FONT *oldfont = font;
10763 font = get_zc_font(font_lfont);
10764 jwin_draw_titlebar(screen, window_xofs+3, window_yofs+3, w+6, 18, "Select Combo", true);
10765 font=oldfont;
10766 }
10767
10768
10769 static int32_t _selected_combo=-1, _selected_cset=-1;
10770 bool select_combo_2(int32_t &cmb,int32_t &cs)
10771 {
10772 popup_zqdialog_start();
10773 reset_combo_animations();
10774 reset_combo_animations2();
10775 combopage_animate = zc_get_config("ZQ_GUI","combopage_animate",1);
10776 // static int32_t cmb=0;
10777 int32_t page=cmb>>8;
10778 int32_t tile2=cmb;
10779 int32_t done=0;
10780 int32_t tile_clicked=-1;
10781 int32_t t2;
10782 int32_t copy=-1;
10783 int32_t copycnt=0;
10784
10785 position_mouse_z(0);
10786
10787 go();
10788 int32_t w = 640;
10789 int32_t h = 480;
10790 int32_t window_xofs=(zq_screen_w-w-12)>>1;
10791 int32_t window_yofs=(zq_screen_h-h-25-6)>>1;
10792 int32_t screen_xofs=window_xofs+6;
10793 int32_t screen_yofs=window_yofs+25;
10794 int32_t panel_yofs=3;
10795 int32_t mul = 2;
10796 FONT *tfont = get_zc_font(font_lfont_l);
10797
10798 draw_combo_list_window();
10799 draw_combos(page,cs,combo_cols);
10800 combo_info(cmb,tile2,cs,copy,copycnt,page,4);
10801
10802 while(gui_mouse_b())
10803 {
10804 /* do nothing */
10805 rest(1);
10806 }
10807
10808 bool bdown=false;
10809 int32_t f=0;
10810 int otl = cmb, otl2 = tile2;
10811
10812 do
10813 {
10814 HANDLE_CLOSE_ZQDLG();
10815 if(exiting_program) break;
10816 rest(4);
10817 bool redraw=false;
10818
10819 if(mouse_z<0)
10820 {
10821 if(page<COMBO_PAGES-1)
10822 {
10823 ++page;
10824 cmb=tile2=(page<<8)+(cmb&0xFF);
10825 }
10826
10827 position_mouse_z(0);
10828 redraw=true;
10829 }
10830 else if(mouse_z>0)
10831 {
10832 if(page>0)
10833 {
10834 --page;
10835 cmb=tile2=(page<<8)+(cmb&0xFF);
10836 }
10837
10838 position_mouse_z(0);
10839 redraw=true;
10840 }
10841
10842 if(keypressed())
10843 {
10844 switch(readkey()>>8)
10845 {
10846 case KEY_DEL:
10847 cmb=0;
10848 done=2;
10849 break;
10850
10851 case KEY_ENTER_PAD:
10852 case KEY_ENTER:
10853 done=2;
10854 break;
10855
10856 case KEY_ESC:
10857 done=1;
10858 break;
10859
10860 case KEY_F1:
10861 onHelp();
10862 break;
10863
10864 case KEY_SPACE:
10865 combo_cols=!combo_cols;
10866 redraw=true;
10867 break;
10868
10869 case KEY_EQUALS:
10870 case KEY_PLUS_PAD:
10871 cs = (cs<13) ? cs+1:0;
10872 redraw=true;
10873 break;
10874
10875 case KEY_MINUS:
10876 case KEY_MINUS_PAD:
10877 cs = (cs>0) ? cs-1:13;
10878 redraw=true;
10879 break;
10880
10881 case KEY_UP:
10882 sel_combo(cmb,tile2,-COMBOS_PER_ROW,combo_cols);
10883 redraw=true;
10884 break;
10885
10886 case KEY_DOWN:
10887 sel_combo(cmb,tile2,COMBOS_PER_ROW,combo_cols);
10888 redraw=true;
10889 break;
10890
10891 case KEY_LEFT:
10892 sel_combo(cmb,tile2,-1,combo_cols);
10893 redraw=true;
10894 break;
10895
10896 case KEY_RIGHT:
10897 sel_combo(cmb,tile2,1,combo_cols);
10898 redraw=true;
10899 break;
10900
10901 case KEY_PGUP:
10902 if(page>0)
10903 {
10904 --page;
10905 cmb=tile2=(page<<8)+(cmb&0xFF);
10906 }
10907
10908 redraw=true;
10909 break;
10910
10911 case KEY_PGDN:
10912 if(page<COMBO_PAGES-1)
10913 {
10914 ++page;
10915 cmb=tile2=(page<<8)+(cmb&0xFF);
10916 }
10917
10918 redraw=true;
10919 break;
10920
10921 case KEY_P:
10922 {
10923 int32_t choosepage=getnumber("Goto Page", (PreFillComboEditorPage?page:0));
10924
10925 if(!cancelgetnum)
10926 page=(zc_min(choosepage,COMBO_PAGES-1));
10927
10928 cmb=tile2=(page<<8)+(cmb&0xFF);
10929 redraw=true;
10930 break;
10931 }
10932 }
10933
10934 clear_keybuf();
10935 }
10936
10937 if(gui_mouse_b()&1)
10938 {
10939 if(isinRect(gui_mouse_x(),gui_mouse_y(),window_xofs + w + 12 - 21, window_yofs + 5, window_xofs + w +12 - 21 + 15, window_yofs + 5 + 13))
10940 {
10941 if(do_x_button(screen, w+12+window_xofs - 21, 5+window_yofs))
10942 {
10943 done=1;
10944 }
10945 }
10946
10947 int32_t x=gui_mouse_x()-screen_xofs;
10948 int32_t y=gui_mouse_y()-screen_yofs;
10949
10950 if(y>=0 && y<208*mul)
10951 {
10952 x=zc_min(zc_max(x,0),(320*mul)-1);
10953 int32_t t;
10954
10955 if(!combo_cols)
10956 {
10957 t = (y>>5)*COMBOS_PER_ROW + (x>>5);
10958 }
10959 else
10960 {
10961 t = ((x>>7)*52) + ((x>>5)&3) + ((y>>5)<<2);
10962 }
10963
10964 bound(t,0,255);
10965 t+=page<<8;
10966 cmb=tile2=t;
10967
10968 if(tile_clicked!=t)
10969 {
10970 dclick_status=DCLICK_NOT;
10971 }
10972 else if(dclick_status == DCLICK_AGAIN)
10973 {
10974 while(gui_mouse_b())
10975 {
10976 /* do nothing */
10977 }
10978
10979 if(!combo_cols)
10980 {
10981 t2 = (y>>5)*COMBOS_PER_ROW + (x>>5);
10982 }
10983 else
10984 {
10985 t2 = ((x>>7)*52) + ((x>>5)&3) + ((y>>5)<<2);
10986 }
10987
10988 if(t2!=t)
10989 {
10990 dclick_status=DCLICK_NOT;
10991 }
10992 else
10993 {
10994 done=2;
10995 }
10996 }
10997
10998 tile_clicked=t;
10999 }
11000 else if(y>=(208*mul) && x>(300*mul) && !bdown)
11001 {
11002 if(y<(224*mul)+panel_yofs && page>0)
11003 {
11004 --page;
11005 redraw=true;
11006 }
11007
11008 if(y>=(224*mul)+panel_yofs && page<COMBO_PAGES-1)
11009 {
11010 ++page;
11011 redraw=true;
11012 }
11013
11014 bdown=true;
11015 }
11016
11017 if(!bdown && isinRect(x,y,(247*mul),(213*mul),((247+44)*mul),((213+21)*mul)))
11018 {
11019 FONT *tf = font;
11020 font = tfont;
11021
11022 if(do_text_button((247*mul)+screen_xofs,(213*mul)+screen_yofs+panel_yofs,(44*mul),(21*mul),"Done"))
11023 {
11024 done=2;
11025 }
11026
11027 font = tf;
11028 }
11029 else if(!bdown && isinRect(x,y,320,440+panel_yofs,320+16,440+panel_yofs+16))
11030 {
11031 FONT *tf = font;
11032 font = tfont;
11033
11034 //do_scheckbox(screen2,320,440+panel_yofs,16,jwin_pal[jcTEXTBG],jwin_pal[jcTEXTFG],combopage_animate,screen_xofs,screen_yofs);
11035 combopage_animate = combopage_animate ? 0 : 1;
11036 zc_set_config("ZQ_GUI","combopage_animate",combopage_animate);
11037 redraw = true;
11038
11039 font = tf;
11040 }
11041
11042 bdown=true;
11043 }
11044
11045 bool r_click = false;
11046
11047 if(gui_mouse_b()&2 && !bdown)
11048 {
11049 int32_t x=gui_mouse_x()+screen_xofs;
11050 int32_t y=gui_mouse_y()+screen_yofs;
11051
11052 if(y>=0 && y<208*mul)
11053 {
11054 x=zc_min(zc_max(x,0),(320*mul)-1);
11055 int32_t t;
11056
11057 if(!combo_cols)
11058 t = (y>>5)*COMBOS_PER_ROW + (x>>5);
11059 else
11060 t = ((x>>7)*52) + ((x>>5)&3) + ((y>>5)<<2);
11061
11062 bound(t,0,255);
11063 t+=page<<8;
11064
11065 if(t<zc_min(cmb,tile2) || t>zc_max(cmb,tile2))
11066 cmb=tile2=t;
11067 }
11068
11069 bdown = r_click = true;
11070 f=8;
11071 }
11072
11073 if(gui_mouse_b()==0)
11074 bdown=false;
11075
11076 if((f%8) || InvalidBG == 1)
11077 redraw = true;
11078 if(otl != cmb || otl2 != tile2)
11079 {
11080 otl = cmb;
11081 otl2 = tile2;
11082 redraw = true;
11083 }
11084
11085 if(redraw || combopage_animate)
11086 draw_combos(page,cs,combo_cols);
11087
11088 combo_info(cmb,tile2,cs,copy,copycnt,page,4);
11089
11090 if(f&8)
11091 {
11092 int32_t x,y;
11093
11094 for(int32_t i=zc_min(cmb,tile2); i<=zc_max(cmb,tile2); i++)
11095 {
11096 if((i>>8)==page)
11097 {
11098 int32_t t=i&255;
11099
11100 if(!combo_cols)
11101 {
11102 x=(t%COMBOS_PER_ROW)<<5;
11103 y=(t/COMBOS_PER_ROW)<<5;
11104 }
11105 else
11106 {
11107 x=((t&3) + ((t/52)<<2)) << 5;
11108 y=((t%52)>>2) << 5;
11109 }
11110
11111 safe_rect(screen,x+screen_xofs,y+screen_yofs,x+screen_xofs+(16*mul)-1,y+screen_yofs+(16*mul)-1,vc(CmbPgCursorCol),2);
11112 }
11113 }
11114
11115 SCRFIX();
11116 }
11117
11118 ++f;
11119
11120 }
11121 while(!done);
11122
11123 while(gui_mouse_b())
11124 {
11125 /* do nothing */
11126 rest(1);
11127 }
11128
11129 comeback();
11130 setup_combo_animations();
11131 setup_combo_animations2();
11132
11133 bool ret = done==2;
11134 if(ret)
11135 {
11136 _selected_combo = cmb;
11137 _selected_cset = cs;
11138 }
11139
11140 popup_zqdialog_end();
11141 return ret;
11142 }
11143
11144 bool select_combo_3(int32_t &cmb,int32_t &cs)
11145 {
11146 if(_selected_combo < 0)
11147 {
11148 _selected_combo = Combo;
11149 _selected_cset = CSet;
11150 }
11151 cmb = _selected_combo;
11152 cs = _selected_cset;
11153 return select_combo_2(cmb,cs);
11154 }
11155
11156 bool advpaste(int32_t tile, int32_t tile2, int32_t copy)
11157 {
11158 static bitstring pasteflags;
11159 static const vector<CheckListInfo> advp_names =
11160 {
11161 { "Tile" },
11162 { "CSet2" },
11163 { "Solidity" },
11164 { "Animation" },
11165 { "Type" },
11166 { "Inherent Flag" },
11167 { "Attribytes" },
11168 { "Attrishorts" },
11169 { "Attributes" },
11170 { "Flags", "The 16 Flags on the 'Flags' tab" },
11171 { "Gen. Flags", "The 2 'General Flags' on the 'Flags' tab" },
11172 { "Label" },
11173 { "Script" },
11174 { "Effect" },
11175 { "Triggers Tab" },
11176 { "Lifting Tab" },
11177 { "Gen: Movespeed", "The Movespeed related values from the 'General' tab" },
11178 { "Gen: SFX", "The SFX related values from the 'General' tab" },
11179 { "Gen: Sprites", "The Sprites related values from the 'General' tab" },
11180 };
11181 if(!call_checklist_dialog("Advanced Paste",advp_names,pasteflags))
11182 return false;
11183
11184 //Paste to each combo in the range
11185 for(int32_t i=zc_min(tile,tile2); i<=zc_max(tile,tile2); ++i)
11186 {
11187 combobuf[i].advpaste(combobuf[copy], pasteflags);
11188 }
11189
11190 if(pasteflags.get(CMB_ADVP_TILE)) //reset animations if needed
11191 {
11192 setup_combo_animations();
11193 setup_combo_animations2();
11194 }
11195
11196 return true;
11197 }
11198
11199 int32_t combo_screen(int32_t pg, int32_t tl)
11200 {
11201 popup_zqdialog_start();
11202 reset_combo_animations();
11203 reset_combo_animations2();
11204 combopage_animate = zc_get_config("ZQ_GUI","combopage_animate",1);
11205 static int32_t tile=0;
11206 static int32_t page=0;
11207
11208 if(pg>-1)
11209 page = pg;
11210
11211 if(tl>-1)
11212 tile = tl;
11213
11214 int32_t tile2=tile;
11215 int32_t done=0;
11216 int32_t cs = CSet;
11217 int32_t copy=-1;
11218 int32_t copycnt=0;
11219
11220 int32_t tile_clicked=-1;
11221 int32_t t2;
11222
11223 bool masscopy;
11224
11225 go();
11226 int32_t w = 640;
11227 int32_t h = 480;
11228 int32_t window_xofs=(zq_screen_w-w-12)>>1;
11229 int32_t window_yofs=(zq_screen_h-h-25-6)>>1;
11230 int32_t screen_xofs=window_xofs+6;
11231 int32_t screen_yofs=window_yofs+25;
11232 int32_t panel_yofs=3;
11233 int32_t mul = 2;
11234 FONT *tfont = get_zc_font(font_lfont_l);
11235
11236 draw_combo_list_window();
11237 draw_combos(page,cs,combo_cols);
11238 combo_info(tile,tile2,cs,copy,copycnt,page,6);
11239 go_combos();
11240 position_mouse_z(0);
11241
11242 while(gui_mouse_b())
11243 {
11244 /* do nothing */
11245 }
11246
11247 bool bdown=false;
11248 int32_t f=0;
11249 int otl = tile, otl2 = tile2;
11250
11251 do
11252 {
11253 HANDLE_CLOSE_ZQDLG();
11254 if(exiting_program) break;
11255 rest(4);
11256 bool redraw=false;
11257
11258 if(mouse_z<0)
11259 {
11260 if(page<COMBO_PAGES-1)
11261 {
11262 ++page;
11263 tile=tile2=(page<<8)+(tile&0xFF);
11264 }
11265
11266 position_mouse_z(0);
11267 redraw=true;
11268 }
11269 else if(mouse_z>0)
11270 {
11271 if(page>0)
11272 {
11273 --page;
11274 tile=tile2=(page<<8)+(tile&0xFF);
11275 }
11276
11277 position_mouse_z(0);
11278 redraw=true;
11279 }
11280
11281 if(keypressed())
11282 {
11283 switch(readkey()>>8)
11284 {
11285 case KEY_ENTER_PAD:
11286 case KEY_ENTER:
11287 done=2;
11288 break;
11289
11290 case KEY_ESC:
11291 done=1;
11292 break;
11293
11294 case KEY_F1:
11295 onHelp();
11296 break;
11297
11298 case KEY_SPACE:
11299 combo_cols=!combo_cols;
11300 redraw=true;
11301 break;
11302
11303 case KEY_EQUALS:
11304 case KEY_PLUS_PAD:
11305 if(CHECK_CTRL_CMD)
11306 {
11307 int32_t amnt = (key[KEY_LSHIFT] || key[KEY_RSHIFT]) ?
11308 ((key[KEY_ALT] || key[KEY_ALTGR]) ? TILES_PER_PAGE*10 : TILES_PER_ROW)
11309 : ((key[KEY_ALT] || key[KEY_ALTGR]) ? TILES_PER_PAGE : 1);
11310
11311 for(int32_t i=zc_min(tile,tile2); i<=zc_max(tile,tile2); ++i)
11312 {
11313 combobuf[i].set_tile(wrap(combobuf[i].o_tile + amnt,
11314 0, NEWMAXTILES-1));
11315 }
11316
11317 setup_combo_animations();
11318 redraw=true;
11319 }
11320 else
11321 {
11322 cs = (cs<13) ? cs+1:0;
11323 redraw=true;
11324 }
11325
11326 break;
11327
11328 case KEY_MINUS:
11329 case KEY_MINUS_PAD:
11330 if(CHECK_CTRL_CMD)
11331 {
11332 int32_t amnt = (key[KEY_LSHIFT] || key[KEY_RSHIFT]) ?
11333 ((key[KEY_ALT] || key[KEY_ALTGR]) ? TILES_PER_PAGE*10 : TILES_PER_ROW)
11334 : ((key[KEY_ALT] || key[KEY_ALTGR]) ? TILES_PER_PAGE : 1);
11335
11336 for(int32_t i=zc_min(tile,tile2); i<=zc_max(tile,tile2); ++i)
11337 {
11338 combobuf[i].set_tile(wrap(combobuf[i].o_tile - amnt,
11339 0, NEWMAXTILES-1));
11340 }
11341
11342 setup_combo_animations();
11343 redraw=true;
11344 }
11345 else
11346 {
11347 cs = (cs>0) ? cs-1:13;
11348 redraw=true;
11349 }
11350
11351 break;
11352
11353 case KEY_UP:
11354 sel_combo(tile,tile2,-COMBOS_PER_ROW,combo_cols);
11355 redraw=true;
11356 break;
11357
11358 case KEY_DOWN:
11359 sel_combo(tile,tile2,COMBOS_PER_ROW,combo_cols);
11360 redraw=true;
11361 break;
11362
11363 case KEY_LEFT:
11364 sel_combo(tile,tile2,-1,combo_cols);
11365 redraw=true;
11366 break;
11367
11368 case KEY_RIGHT:
11369 sel_combo(tile,tile2,1,combo_cols);
11370 redraw=true;
11371 break;
11372
11373 case KEY_PGUP:
11374 if(page>0)
11375 {
11376 --page;
11377 tile=tile2=(page<<8)+(tile&0xFF);
11378 }
11379
11380 redraw=true;
11381 break;
11382
11383 case KEY_PGDN:
11384 if(page<COMBO_PAGES-1)
11385 {
11386 ++page;
11387 tile=tile2=(page<<8)+(tile&0xFF);
11388 }
11389
11390 redraw=true;
11391 break;
11392
11393 case KEY_A:
11394 {
11395 tile=(page<<8);
11396 tile2=(page<<8)+(0xFF);
11397 }
11398
11399 redraw=true;
11400 break;
11401
11402 case KEY_P:
11403 {
11404 int32_t choosepage = getnumber("Goto Page", (PreFillComboEditorPage?page:0));
11405
11406 if(!cancelgetnum)
11407 page=(zc_min(choosepage,COMBO_PAGES-1));
11408
11409 tile=tile2=(page<<8)+(tile&0xFF);
11410 redraw=true;
11411 }
11412 break;
11413
11414 case KEY_U:
11415 comeback_combos();
11416 redraw=true;
11417 break;
11418
11419 case KEY_E:
11420 go_combos();
11421 edit_combo(tile,false,cs);
11422 redraw=true;
11423 setup_combo_animations();
11424 setup_combo_animations2();
11425 break;
11426
11427 case KEY_C:
11428 go_combos();
11429 copy=zc_min(tile,tile2);
11430 copycnt=abs(tile-tile2)+1;
11431 redraw=true;
11432 break;
11433
11434 case KEY_H:
11435 for(int32_t i=zc_min(tile,tile2); i<=zc_max(tile,tile2); i++)
11436 {
11437 combobuf[i].flip^=1;
11438 byte w2=combobuf[i].walk;
11439 combobuf[i].walk=((w2& ~0x33)>>2 | (w2&0x33)<<2);
11440 w2=combobuf[i].csets;
11441 combobuf[i].csets= (((w2& ~0x50)>>1 | (w2&0x50)<<1) & ~0x0F) | (w2 & 0x0F);
11442 }
11443
11444 redraw=true;
11445 saved=false;
11446 break;
11447
11448 case KEY_M:
11449 if((copy!=-1)&&(copy!=zc_min(tile,tile2)))
11450 {
11451 move_combos(tile,tile2,copy,copycnt);
11452 saved=false;
11453 }
11454
11455 redraw=true;
11456 break;
11457
11458 case KEY_S:
11459 tile=tile2=zc_min(tile,tile2);
11460
11461 if(copy>=0 && tile!=copy)
11462 {
11463 go_combos();
11464
11465 for(int32_t i=0; i<copycnt; i++)
11466 {
11467 zc_swap(combobuf[copy+i],combobuf[tile+i]);
11468 }
11469
11470 saved=false;
11471 setup_combo_animations();
11472 setup_combo_animations2();
11473 }
11474
11475 redraw=true;
11476 copy=-1;
11477 break;
11478
11479 case KEY_V:
11480 if((CHECK_CTRL_CMD) && copy != -1)
11481 {
11482 if(advpaste(tile, tile2, copy))
11483 {
11484 saved=false;
11485 redraw=true;
11486 copy=-1;
11487 }
11488
11489 break;
11490 }
11491
11492 masscopy=(key[KEY_LSHIFT] || key[KEY_RSHIFT])?1:0;
11493
11494 if(copy==-1)
11495 {
11496 go_combos();
11497
11498 for(int32_t i=zc_min(tile,tile2); i<=zc_max(tile,tile2); i++)
11499 {
11500 combobuf[i].flip^=2;
11501 byte w2=combobuf[i].walk;
11502 combobuf[i].walk=(w2&0x55)<<1 | (w2& ~0x55)>>1;
11503 w2=combobuf[i].csets;
11504 combobuf[i].csets= (((w2&0x30)<<2 | (w2& ~0x30)>>2) & ~0x0F) | (w2 & 0x0F);
11505 }
11506
11507 saved=false;
11508 }
11509 else
11510 {
11511 go_combos();
11512 copy_combos(tile,tile2,copy,copycnt,masscopy);
11513 setup_combo_animations();
11514 setup_combo_animations2();
11515 saved=false;
11516 }
11517
11518 redraw=true;
11519 break;
11520 case KEY_R:
11521 for(int32_t i=zc_min(tile,tile2); i<=zc_max(tile,tile2); i++)
11522 {
11523 combobuf[i].flip = rotate_value(combobuf[i].flip);
11524 combobuf[i].walk = rotate_walk(combobuf[i].walk);
11525 combobuf[i].csets = rotate_cset(combobuf[i].csets);
11526 }
11527
11528 redraw=true;
11529 saved=false;
11530 break;
11531
11532 case KEY_I:
11533 {
11534 // rev.1509; Can now insert/remove all selected combos
11535 int32_t z=tile;
11536 int32_t numSelected = abs(tile-tile2) + 1;
11537 tile=zc_min(tile,tile2);
11538 tile2=MAXCOMBOS;
11539 copy = tile + numSelected; // copy=tile+1;
11540 copycnt = MAXCOMBOS-tile-numSelected; // copycnt=MAXCOMBOS-tile;
11541
11542 if(key[KEY_LSHIFT]||key[KEY_RSHIFT])
11543 {
11544 char buf[64];
11545
11546 if(numSelected>1)
11547 sprintf(buf,"Remove combos %d - %d?",tile, copy-1);
11548 else
11549 sprintf(buf,"Remove combo %d?",tile);
11550
11551 if(jwin_alert("Confirm Remove",buf,"This will offset all of the combos that follow!",NULL,"&Yes","&No",'y','n',get_zc_font(font_lfont))==1)
11552 {
11553 move_combos(tile,tile2,copy, copycnt);
11554 //don't allow the user to undo; quest combo references are incorrect -DD
11555 go_combos();
11556 redraw=true;
11557 saved=false;
11558 }
11559 }
11560 else
11561 {
11562 char buf[64];
11563
11564 if(numSelected>1)
11565 sprintf(buf,"Insert %d blank combos?",numSelected);
11566 else
11567 sprintf(buf,"Insert a blank combo?");
11568
11569 if(jwin_alert("Confirm Insert",buf,"This will offset all of the combos that follow!",NULL,"&Yes","&No",'y','n',get_zc_font(font_lfont))==1)
11570 {
11571 move_combos(copy,tile2,tile, copycnt);
11572 go_combos();
11573 redraw=true;
11574 saved=false;
11575 }
11576 }
11577
11578 copy=-1;
11579 tile2=tile=z;
11580 }
11581 break;
11582
11583 case KEY_DEL:
11584 {
11585 char buf[40];
11586
11587 if(tile==tile2)
11588 {
11589 sprintf(buf,"Delete combo %d?",tile);
11590 }
11591 else
11592 {
11593 sprintf(buf,"Delete combos %d-%d?",zc_min(tile,tile2),zc_max(tile,tile2));
11594 }
11595
11596 if(jwin_alert("Confirm Delete",buf,NULL,NULL,"&Yes","&No",'y','n',get_zc_font(font_lfont))==1)
11597 {
11598 go_combos();
11599
11600 for(int32_t i=zc_min(tile,tile2); i<=zc_max(tile,tile2); i++)
11601 {
11602 clear_combo(i);
11603 }
11604
11605 tile=tile2=zc_min(tile,tile2);
11606 redraw=true;
11607 saved=false;
11608 setup_combo_animations();
11609 setup_combo_animations2();
11610 }
11611 }
11612 break;
11613 }
11614
11615 clear_keybuf();
11616 }
11617
11618 if(gui_mouse_b()&1)
11619 {
11620 if(isinRect(gui_mouse_x(),gui_mouse_y(),window_xofs + w + 12 - 21, window_yofs + 5, window_xofs + w +12 - 21 + 15, window_yofs + 5 + 13))
11621 {
11622 if(do_x_button(screen, w+12+window_xofs - 21, 5+window_yofs))
11623 {
11624 done=1;
11625 }
11626 }
11627
11628 int32_t x=gui_mouse_x()-screen_xofs;
11629 int32_t y=gui_mouse_y()-screen_yofs;
11630
11631 if(y>=0 && y<(208*mul))
11632 {
11633 x=zc_min(zc_max(x,0),(320*mul)-1);
11634 int32_t t;
11635
11636 if(!combo_cols)
11637 {
11638 t = (y>>5)*COMBOS_PER_ROW + (x>>5);
11639 }
11640 else
11641 {
11642 t = ((x>>7)*52) + ((x>>5)&3) + ((y>>5)<<2);
11643 }
11644
11645 bound(t,0,255);
11646 t+=page<<8;
11647
11648 if(key[KEY_LSHIFT] || key[KEY_RSHIFT])
11649 {
11650 tile2=t;
11651 }
11652 else
11653 {
11654 tile=tile2=t;
11655 }
11656
11657 if(tile_clicked!=t)
11658 {
11659 dclick_status=DCLICK_NOT;
11660 }
11661 else if(dclick_status == DCLICK_AGAIN)
11662 {
11663 while(gui_mouse_b())
11664 {
11665 /* do nothing */
11666 rest(1);
11667 }
11668
11669 if(!combo_cols)
11670 {
11671 t2 = (y>>4)*COMBOS_PER_ROW + (x>>4);
11672 }
11673 else
11674 {
11675 t2 = ((x>>6)*52) + ((x>>4)&3) + ((y>>4)<<2);
11676 }
11677
11678 bound(t2,0,255);
11679 t2+=page<<8;
11680
11681 if(t2!=t)
11682 {
11683 dclick_status=DCLICK_NOT;
11684 }
11685 else
11686 {
11687 go_combos();
11688 edit_combo(tile,false,cs);
11689 redraw=true;
11690 setup_combo_animations();
11691 setup_combo_animations2();
11692 }
11693 }
11694
11695 tile_clicked=t;
11696 }
11697 else if(x>(300*mul) && !bdown)
11698 {
11699 if(y<(224*mul)+panel_yofs && page>0)
11700 {
11701 --page;
11702 redraw=true;
11703 }
11704
11705 if(y>=(224*mul)+panel_yofs && page<COMBO_PAGES-1)
11706 {
11707 ++page;
11708 redraw=true;
11709 }
11710
11711 bdown=true;
11712 }
11713
11714 if(!bdown && isinRect(x,y,(202*mul),(213*mul)+panel_yofs,(202+44)*mul,(213+21)*mul))
11715 {
11716 FONT *tf = font;
11717 font = tfont;
11718
11719 if(do_text_button((202*mul)+screen_xofs,(213*mul)+screen_yofs+panel_yofs,(44*mul),(21*mul),"Edit"))
11720 {
11721 font = tf;
11722 edit_combo(tile,false,cs);
11723 redraw=true;
11724 }
11725
11726 font = tf;
11727 }
11728 else if(!bdown && isinRect(x,y,(247*mul),(213*mul)+panel_yofs,(247+44)*mul,(213+21)*mul))
11729 {
11730 FONT *tf = font;
11731 font = tfont;
11732
11733 if(do_text_button((247*mul)+screen_xofs,(213*mul)+screen_yofs+panel_yofs,(44*mul),(21*mul),"Done"))
11734 {
11735 done=1;
11736 }
11737
11738 font = tf;
11739 }
11740 else if(!bdown && isinRect(x,y,320,440+panel_yofs,320+16,440+panel_yofs+16))
11741 {
11742 FONT *tf = font;
11743 font = tfont;
11744
11745 //do_scheckbox(screen2,320,440+panel_yofs,16,jwin_pal[jcTEXTBG],jwin_pal[jcTEXTFG],combopage_animate,screen_xofs,screen_yofs);
11746 combopage_animate = combopage_animate ? 0 : 1;
11747 zc_set_config("ZQ_GUI","combopage_animate",combopage_animate);
11748 redraw = true;
11749
11750 font = tf;
11751 }
11752
11753 bdown=true;
11754 }
11755
11756 bool r_click = false;
11757
11758 if(gui_mouse_b()&2 && !bdown)
11759 {
11760 int32_t x=gui_mouse_x()-screen_xofs;
11761 int32_t y=gui_mouse_y()-screen_yofs;
11762
11763 if(y>=0 && y<(208*mul))
11764 {
11765 x=zc_min(zc_max(x,0),(320*mul)-1);
11766 int32_t t;
11767
11768 if(!combo_cols)
11769 {
11770 t = (y>>5)*COMBOS_PER_ROW + (x>>5);
11771 }
11772 else
11773 {
11774 t = ((x>>7)*52) + ((x>>5)&3) + ((y>>5)<<2);
11775 }
11776
11777 bound(t,0,255);
11778 t+=page<<8;
11779
11780 if(t<zc_min(tile,tile2) || t>zc_max(tile,tile2))
11781 {
11782 tile=tile2=t;
11783 }
11784 }
11785
11786 bdown = r_click = true;
11787 f=8;
11788 }
11789
11790 REDRAW:
11791
11792 if(gui_mouse_b()==0)
11793 bdown=false;
11794
11795 if((f%8) || InvalidBG == 1)
11796 redraw = true;
11797 if(otl != tile || otl2 != tile2)
11798 {
11799 otl = tile;
11800 otl2 = tile2;
11801 redraw = true;
11802 }
11803
11804 if(redraw || combopage_animate)
11805 draw_combos(page,cs,combo_cols);
11806
11807 combo_info(tile,tile2,cs,copy,copycnt,page,6);
11808
11809 if(f&8)
11810 {
11811 int32_t x,y;
11812
11813 for(int32_t i=zc_min(tile,tile2); i<=zc_max(tile,tile2); i++)
11814 {
11815 if((i>>8)==page)
11816 {
11817 int32_t t=i&255;
11818
11819 if(!combo_cols)
11820 {
11821 x=(t%COMBOS_PER_ROW)<<5;
11822 y=(t/COMBOS_PER_ROW)<<5;
11823 }
11824 else
11825 {
11826 x=((t&3) + ((t/52)<<2)) << 5;
11827 y=((t%52)>>2) << 5;
11828 }
11829
11830 safe_rect(screen,x+screen_xofs,y+screen_yofs,x+screen_xofs+(16*mul)-1,y+screen_yofs+(16*mul)-1,vc(CmbPgCursorCol),2);
11831 }
11832 }
11833
11834 SCRFIX();
11835 }
11836
11837 ++f;
11838
11839 //Seriously? There is duplicate code for the r-click menu? -Gleeok
11840 if(r_click)
11841 {
11842 NewMenu rcmenu
11843 {
11844 { "Copy", [&]()
11845 {
11846 go_combos();
11847 copy=zc_min(tile,tile2);
11848 copycnt=abs(tile-tile2)+1;
11849 } },
11850 { "Paste", [&]()
11851 {
11852 if((CHECK_CTRL_CMD) && copy != -1)
11853 {
11854 if(advpaste(tile, tile2, copy))
11855 {
11856 saved=false;
11857 redraw=true;
11858 copy=-1;
11859 }
11860 return;
11861 }
11862
11863 masscopy=(key[KEY_LSHIFT] || key[KEY_RSHIFT])?1:0;
11864
11865 if(copy>-1)
11866 {
11867 go_combos();
11868 copy_combos(tile,tile2,copy,copycnt,masscopy);
11869 setup_combo_animations();
11870 setup_combo_animations2();
11871 saved=false;
11872 }
11873 } },
11874 { "Adv. Paste", [&]()
11875 {
11876 if(copy > -1)
11877 {
11878 if(advpaste(tile, tile2, copy))
11879 {
11880 saved=false;
11881 redraw=true;
11882 copy=-1;
11883 }
11884 }
11885 } },
11886 { "Swap", [&]()
11887 {
11888 tile=tile2=zc_min(tile,tile2);
11889
11890 if(copy>=0 && tile!=copy)
11891 {
11892 go_combos();
11893
11894 for(int32_t i=0; i<copycnt; i++)
11895 {
11896 zc_swap(combobuf[copy+i],combobuf[tile+i]);
11897 }
11898
11899 saved=false;
11900 setup_combo_animations();
11901 setup_combo_animations2();
11902 }
11903 copy=-1;
11904 } },
11905 { "Delete", [&]()
11906 {
11907 string msg;
11908
11909 if(tile==tile2)
11910 msg = fmt::format("Delete combo {}?",tile);
11911 else
11912 msg = fmt::format("Delete combos {}-{}?",zc_min(tile,tile2),zc_max(tile,tile2));
11913 bool didconfirm = false;
11914 AlertDialog("Confirm Delete",msg,
11915 [&](bool ret,bool)
11916 {
11917 if(ret)
11918 didconfirm = true;
11919 }).show();
11920 if(didconfirm)
11921 {
11922 go_combos();
11923
11924 for(int32_t i=zc_min(tile,tile2); i<=zc_max(tile,tile2); i++)
11925 clear_combo(i);
11926
11927 tile=tile2=zc_min(tile,tile2);
11928 saved=false;
11929 }
11930 } },
11931 {},
11932 { "Edit", [&]()
11933 {
11934 go_combos();
11935 edit_combo(tile,false,cs);
11936 } },
11937 { "Insert", [&]()
11938 {
11939 int z = tile;
11940 int count = abs(tile-tile2)+1;
11941 tile = zc_min(tile,tile2);
11942 tile2 = MAXCOMBOS;
11943 copy = tile+count;
11944 copycnt = MAXCOMBOS-tile-count;
11945
11946 string msg;
11947
11948 if(count>1)
11949 msg = fmt::format("Insert combos {} - {}?"
11950 " This will offset all of the combos that follow!",tile, copy-1);
11951 else
11952 msg = fmt::format("Insert combo {}?"
11953 " This will offset all of the combos that follow!",tile);
11954
11955 bool didconfirm = false;
11956 AlertDialog("Confirm Insert",msg,
11957 [&](bool ret,bool)
11958 {
11959 if(ret)
11960 didconfirm = true;
11961 }).show();
11962 if(didconfirm)
11963 move_combos(copy, tile2, tile, copycnt);
11964 else return;
11965
11966 copy = -1;
11967 tile2 = tile = z;
11968
11969 //don't allow the user to undo; quest combo references are incorrect -DD
11970 go_combos();
11971 saved = false;
11972 } },
11973 { "Remove", [&]()
11974 {
11975 int z = tile;
11976 int count = abs(tile-tile2)+1;
11977 tile = zc_min(tile,tile2);
11978 tile2 = MAXCOMBOS;
11979 copy = tile+count;
11980 copycnt = MAXCOMBOS-tile-count;
11981
11982 string msg;
11983
11984 if(count>1)
11985 msg = fmt::format("Remove combos {} - {}?"
11986 " This will offset all of the combos that follow!",tile, copy-1);
11987 else
11988 msg = fmt::format("Remove combo {}?"
11989 " This will offset all of the combos that follow!",tile);
11990
11991 bool didconfirm = false;
11992 AlertDialog("Confirm Remove",msg,
11993 [&](bool ret,bool)
11994 {
11995 if(ret)
11996 didconfirm = true;
11997 }).show();
11998 if(didconfirm)
11999 move_combos(tile, tile2, copy, copycnt);
12000 else return;
12001
12002 copy = -1;
12003 tile2 = tile = z;
12004
12005 //don't allow the user to undo; quest combo references are incorrect -DD
12006 go_combos();
12007 saved = false;
12008 } },
12009 {},
12010 { "Locations", [&]()
12011 {
12012 int32_t z = Combo;
12013 Combo = tile;
12014 onComboLocationReport();
12015 Combo = z;
12016 } },
12017 };
12018 rcmenu.pop(window_mouse_x(),window_mouse_y());
12019 redraw = true;
12020 r_click = false;
12021 goto REDRAW;
12022 }
12023
12024 }
12025 while(!done);
12026
12027 while(gui_mouse_b())
12028 rest(1);
12029 comeback();
12030 setup_combo_animations();
12031 setup_combo_animations2();
12032 _selected_combo = tile;
12033 _selected_cset = cs;
12034 popup_zqdialog_end();
12035 return done-1;
12036 }
12037
12038 int32_t onCombos()
12039 {
12040 // reset_combo_animations();
12041 combo_screen(-1,-1);
12042 // setup_combo_animations();
12043 refresh(rALL);
12044 return D_O_K;
12045 }
12046
12047 int32_t d_ctile_proc(int32_t msg,DIALOG *d,int32_t c)
12048 {
12049 //these are here to bypass compiler warnings about unused arguments
12050 d=d;
12051 c=c;
12052
12053 if(msg==MSG_CLICK)
12054 {
12055 int32_t t=curr_combo.o_tile;
12056 int32_t f=curr_combo.flip;
12057
12058 if(select_tile(t,f,1,CSet,true,0,true))
12059 {
12060 curr_combo.tile=t;
12061 curr_combo.o_tile=t;
12062 curr_combo.flip=f;
12063 return D_REDRAW;
12064 }
12065 }
12066
12067 return D_O_K;
12068 }
12069
12070 int32_t d_combo_loader(int32_t msg,DIALOG *d,int32_t c)
12071 {
12072 //these are here to bypass compiler warnings about unused arguments
12073 c=c;
12074
12075 if(msg==MSG_DRAW)
12076 {
12077 FONT *f = get_zc_font(font_lfont_l);
12078 textprintf_ex(screen,f,d->x,d->y,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"Tile:");
12079 textprintf_ex(screen,f,d->x+((1.5)*36),d->y,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d",curr_combo.o_tile);
12080 textprintf_ex(screen,f,d->x,d->y+(14),jwin_pal[jcBOXFG],jwin_pal[jcBOX],"Flip:");
12081 textprintf_ex(screen,f,d->x+((1.5)*36),d->y+(14),jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d",curr_combo.flip);
12082 textprintf_ex(screen,f,d->x,d->y+(36),jwin_pal[jcBOXFG],jwin_pal[jcBOX],"CSet2:");
12083 }
12084
12085 return D_O_K;
12086 }
12087
12088 int32_t click_d_ctile_proc()
12089 {
12090 d_ctile_proc(MSG_CLICK,NULL,0);
12091 return D_REDRAW;
12092 }
12093
12094 int32_t click_d_combo_proc();
12095
12096 const char *comboscriptdroplist(int32_t index, int32_t *list_size)
12097 {
12098 if(index<0)
12099 {
12100 *list_size = bidcomboscripts_cnt;
12101 return NULL;
12102 }
12103
12104 return bidcomboscripts[index].first.c_str();
12105 }
12106 9 ListData comboscript_list(comboscriptdroplist, &font);
12107
12108 bool call_combo_editor(int32_t);
12109 bool edit_combo(int32_t c,bool freshen,int32_t cs)
12110 {
12111 FONT* ofont = font;
12112 //CSet = cs;
12113 reset_combo_animations();
12114 reset_combo_animations2();
12115 bool edited = call_combo_editor(c);
12116 font = ofont;
12117
12118 if(freshen)
12119 {
12120 refresh(rALL);
12121 }
12122
12123 setup_combo_animations();
12124 setup_combo_animations2();
12125
12126 return edited;
12127 }
12128
12129 int32_t d_itile_proc(int32_t msg,DIALOG *d,int32_t)
12130 {
12131 switch(msg)
12132 {
12133 case MSG_CLICK:
12134 {
12135 int32_t cs = d->d2;
12136 int32_t f = 0;
12137
12138 if(select_tile(d->d1,f,1,cs,true))
12139 {
12140 int32_t ok=1;
12141
12142 if(newtilebuf[d->d1].format==tf8Bit)
12143 jwin_alert("Warning",
12144 "You have selected an 8-bit tile.",
12145 "It will not be drawn correctly",
12146 "on the file select screen.",
12147 "&OK",NULL,'o',0,get_zc_font(font_lfont));
12148
12149 return D_REDRAW;
12150 }
12151 }
12152 break;
12153
12154 case MSG_DRAW:
12155 d->w = 32+4;
12156 d->h = 32+4;
12157
12158 BITMAP *buf = create_bitmap_ex(8,16,16);
12159 BITMAP *bigbmp = create_bitmap_ex(8,d->w,d->h);
12160
12161 if(buf && bigbmp)
12162 {
12163 clear_bitmap(buf);
12164 overtile16(buf,d->d1,0,0,d->fg,0);
12165 stretch_blit(buf, bigbmp, 0,0, 16, 16, 2, 2, d->w-4, d->h-4);
12166 destroy_bitmap(buf);
12167 jwin_draw_frame(bigbmp,0, 0, d->w,d->h, FR_DEEP);
12168 blit(bigbmp,screen,0,0,d->x-1,d->y-1,d->w,d->h);
12169 destroy_bitmap(bigbmp);
12170 }
12171
12172 break;
12173 }
12174
12175 return D_O_K;
12176 }
12177
12178 static DIALOG icon_dlg[] =
12179 {
12180 /* (dialog proc) (x) (y) (w) (h) (fg) (bg) (key) (flags) (d1) (d2) (dp) */
12181 { jwin_win_proc, 70, 70, 170, 104, vc(14), vc(1), 0, D_EXIT, 0, 0, (void *) "Game Icons", NULL, NULL },
12182 { d_timer_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL },
12183 { d_itile_proc, 108+3, 112, 20, 20, 0, 0, 0, 0, 0, 6, NULL, NULL, NULL },
12184 { d_itile_proc, 138+3, 112, 20, 20, 0, 0, 0, 0, 0, 7, NULL, NULL, NULL },
12185 { d_itile_proc, 168+3, 112, 20, 20, 0, 0, 0, 0, 0, 8, NULL, NULL, NULL },
12186 { d_itile_proc, 198+3, 112, 20, 20, 0, 0, 0, 0, 0, 9, NULL, NULL, NULL },
12187 { jwin_button_proc, 90, 145, 61, 21, vc(14), vc(1), 13, D_EXIT, 0, 0, (void *) "OK", NULL, NULL },
12188 { jwin_button_proc, 170, 145, 61, 21, vc(14), vc(1), 27, D_EXIT, 0, 0, (void *) "Cancel", NULL, NULL },
12189 { jwin_text_proc, 108+11, 98, 8, 9, 0, 0, 0, 0, 0, 0, (void *) "0", NULL, NULL },
12190 { jwin_text_proc, 138+11, 98, 8, 9, 0, 0, 0, 0, 0, 0, (void *) "1", NULL, NULL },
12191 { jwin_text_proc, 168+11, 98, 8, 9, 0, 0, 0, 0, 0, 0, (void *) "2", NULL, NULL },
12192 { jwin_text_proc, 198+11, 98, 8, 9, 0, 0, 0, 0, 0, 0, (void *) "3+", NULL, NULL },
12193 { jwin_text_proc, 88, 98, 12, 9, 0, 0, 0, 0, 0, 0, (void *) "Ring:", NULL, NULL },
12194 { NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }
12195 };
12196
12197 int32_t onIcons()
12198 {
12199 PALETTE pal;
12200 // pal = RAMpal;
12201 memcpy(pal,RAMpal,sizeof(RAMpal));
12202 icon_dlg[0].dp2=get_zc_font(font_lfont);
12203
12204 for(int32_t i=0; i<4; i++)
12205 {
12206 icon_dlg[i+2].d1 = QMisc.icons[i];
12207 icon_dlg[i+2].fg = i+6;
12208 load_cset(pal, i+6, pSprite(i+spICON1));
12209 }
12210
12211 zc_set_palette(pal);
12212
12213 large_dialog(icon_dlg);
12214
12215 int32_t ret = do_zqdialog(icon_dlg,7);
12216
12217 if(ret==6)
12218 {
12219 for(int32_t i=0; i<4; i++)
12220 {
12221 if(QMisc.icons[i] != icon_dlg[i+2].d1)
12222 {
12223 QMisc.icons[i] = icon_dlg[i+2].d1;
12224 saved=false;
12225 }
12226 }
12227 }
12228
12229 zc_set_palette(RAMpal);
12230 return D_O_K;
12231 }
12232
12233 // Identical to jwin_frame_proc, but is treated differently by large_dialog()
12234 int32_t d_comboframe_proc(int32_t msg, DIALOG *d, int32_t)
12235 {
12236 if(msg == MSG_DRAW)
12237 {
12238 jwin_draw_frame(screen, d->x, d->y, d->w, d->h, d->d1);
12239 }
12240
12241 return D_O_K;
12242 }
12243
12244 int32_t d_combo_proc(int32_t msg,DIALOG *d,int32_t)
12245 {
12246 switch(msg)
12247 {
12248 case MSG_CLICK:
12249 {
12250 if((d->flags&D_NOCLICK))
12251 break;
12252
12253 int32_t ret = (d->flags & D_EXIT) ? D_CLOSE : D_O_K;
12254 int32_t combo2;
12255 int32_t cs;
12256
12257 if(CHECK_ALT) //place selected cmb/cs
12258 {
12259 if(gui_mouse_b()&1)
12260 {
12261 if(!CHECK_SHIFT)
12262 d->d1 = Combo;
12263 d->fg = CSet;
12264 }
12265
12266 return ret|D_REDRAW;
12267 }
12268 else if(gui_mouse_b()&2||nextcombo_fake_click==2) //clear to 0/0
12269 {
12270 d->d1=0;
12271 d->fg=0;
12272 return ret|D_REDRAW;
12273 }
12274 else if(gui_mouse_b()&1||nextcombo_fake_click==1) //popup combo picker
12275 {
12276 combo2=d->d1;
12277 cs=d->fg;
12278
12279 if((CHECK_CTRL_CMD ? select_combo_3 : select_combo_2)(combo2, cs))
12280 {
12281 d->d1=combo2;
12282 d->fg=cs;
12283 }
12284
12285 return ret|D_REDRAW;
12286 }
12287 else return ret|D_REDRAWME;
12288 }
12289 break;
12290
12291 case MSG_DRAW:
12292 {
12293 d->w = 32;
12294 d->h = 32;
12295
12296 BITMAP *buf = create_bitmap_ex(8,16,16);
12297 BITMAP *bigbmp = create_bitmap_ex(8,d->w,d->h);
12298
12299 if(buf && bigbmp)
12300 {
12301 clear_bitmap(buf);
12302
12303 if(d->d1==-1) // Display curr_combo instead of combobuf
12304 {
12305 newcombo hold = combobuf[0];
12306 combobuf[0] = curr_combo;
12307 putcombo(buf,0,0,0,d->fg);
12308 combobuf[0] = hold;
12309 }
12310 else if(d->d1)
12311 {
12312 putcombo(buf,0,0,d->d1,d->fg);
12313 }
12314
12315 stretch_blit(buf, bigbmp, 0,0, 16, 16, 0, 0, d->w, d->h);
12316 destroy_bitmap(buf);
12317 blit(bigbmp,screen,0,0,d->x-1,d->y-1,d->w,d->h);
12318 destroy_bitmap(bigbmp);
12319 }
12320 }
12321 break;
12322 }
12323 return D_O_K;
12324 }
12325
12326 // Hey, let's have a few hundred more lines of code, why not.
12327
12328 #define MR_4BIT 0
12329 #define MR_8BIT 1
12330
12331 static byte massRecolorSrc4Bit[16]={ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 };
12332 static byte massRecolorDest4Bit[16]={ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 };
12333 static word massRecolor8BitCSets=0; // Which CSets are affected? One bit each.
12334
12335 static byte massRecolorSrc8Bit[16]={ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
12336 static byte massRecolorDest8Bit[16]={ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
12337
12338 static int32_t massRecolorDraggedColor=-1;
12339 static int32_t massRecolorCSet;
12340 static bool massRecolorIgnoreBlank=true;
12341 static byte massRecolorType=MR_4BIT;
12342
12343 // Shows the sets of colors to replace from/to.
12344 // D_CSET: Colors are 0-15 within the current CSet rather than absolute.
12345 // D_SETTABLE: Colors can be dragged and dropped onto this one.
12346 #define D_CSET D_USER
12347 #define D_SETTABLE (D_USER<<1)
12348 int32_t d_mr_cset_proc(int32_t msg, DIALOG* d, int32_t)
12349 {
12350 BITMAP* bmp=screen;
12351 int32_t colorWidth=(d->w-4)/16;
12352 byte* colors=static_cast<byte*>(d->dp);
12353
12354 switch(msg)
12355 {
12356 case MSG_DRAW:
12357 {
12358 jwin_draw_frame(bmp, d->x, d->y, d->w, d->h, FR_DEEP);
12359
12360 int32_t baseColor=((d->flags&D_CSET)!=0) ? massRecolorCSet*16 : 0;
12361 for(int32_t c=0; c<16; c++)
12362 {
12363 rectfill(bmp,
12364 d->x+2+c*colorWidth, d->y+2,
12365 d->x+2+((c+1)*colorWidth)-1, d->y+2+d->h-5,
12366 baseColor+colors[c]);
12367 }
12368 }
12369 break;
12370
12371 case MSG_LPRESS:
12372 {
12373 int32_t x=(gui_mouse_x()-(d->x+2))/colorWidth;
12374
12375 if(x >= 0 && x < 16) //sanity check!
12376 {
12377 massRecolorDraggedColor=colors[x];
12378 }
12379 }
12380 break;
12381
12382 case MSG_LRELEASE: // This isn't exactly right, but it'll do...
12383 if((d->flags&D_SETTABLE)!=0 && massRecolorDraggedColor>=0)
12384 {
12385 int32_t x=(gui_mouse_x()-(d->x+2))/colorWidth;
12386 if(x >= 0 && x < 16) //sanity check!
12387 {
12388 colors[x]=massRecolorDraggedColor;
12389 d->flags|=D_DIRTY;
12390 }
12391 }
12392 massRecolorDraggedColor=-1;
12393 break;
12394 }
12395
12396 return D_O_K;
12397 }
12398
12399 // Used for the full palette in 8-bit mode.
12400 static int32_t d_mr_palette_proc(int32_t msg, DIALOG* d, int32_t)
12401 {
12402 BITMAP* bmp=screen;
12403 int colorWidth=(d->w-4)/16;
12404 d->h = 4+(colorWidth*14);
12405 int colorHeight=colorWidth;
12406
12407 switch(msg)
12408 {
12409 case MSG_DRAW:
12410 {
12411 jwin_draw_frame(bmp, d->x, d->y, d->w, d->h, FR_DEEP);
12412 for(int cset=0; cset<=13; cset++)
12413 {
12414 for(int color=0; color<16; color++)
12415 {
12416 rectfill(bmp,
12417 d->x+2+color*colorWidth,
12418 d->y+2+cset*colorHeight,
12419 d->x+2+((color+1)*colorWidth)-1,
12420 d->y+2+((cset+1)*colorHeight)-1,
12421 cset*16+color);
12422 }
12423 }
12424 }
12425 break;
12426
12427 case MSG_LPRESS:
12428 {
12429 int cset=(gui_mouse_y()-(d->y+2))/colorHeight;
12430 int color=(gui_mouse_x()-(d->x+2))/colorWidth;
12431 massRecolorDraggedColor=cset*16+color;
12432 }
12433 break;
12434 }
12435
12436 return D_O_K;
12437 }
12438
12439 static DIALOG recolor_4bit_dlg[] =
12440 {
12441 // (dialog proc) (x) (y) (w) (h) (fg) (bg) (key) (flags) (d1) (d2) (dp)
12442 { jwin_win_proc, 0, 0, 216, 224, 0, 0, 0, D_EXIT, 0, 0, (void *) "Recolor setup", NULL, NULL },
12443
12444 // 1
12445 { jwin_text_proc, 12, 32, 176, 8, vc(15), vc(1), 0, 0, 0, 0, (void *) "From", NULL, NULL },
12446 { d_mr_cset_proc, 10, 42, 196, 16, 0, 0, 0, D_CSET, 0, 0, (void *)massRecolorSrc4Bit, NULL, NULL },
12447 { jwin_text_proc, 12, 60, 176, 8, vc(15), vc(1), 0, 0, 0, 0, (void *) "To", NULL, NULL },
12448 { d_mr_cset_proc, 10, 70, 196, 16, 0, 0, 0, D_CSET|D_SETTABLE, 0, 0, (void *)massRecolorDest4Bit, NULL, NULL },
12449
12450 // 5
12451 { jwin_text_proc, 12, 96, 176, 8, vc(15), vc(1), 0, 0, 0, 0, (void *) "Apply to which CSets in 8-bit tiles?", NULL, NULL },
12452 { jwin_check_proc, 12, 112, 168, 8, vc(15), vc(1), 0, 0, 1, 0, (void *) "0", NULL, NULL },
12453 { jwin_check_proc, 36, 112, 168, 8, vc(15), vc(1), 0, 0, 1, 0, (void *) "1", NULL, NULL },
12454 { jwin_check_proc, 60, 112, 168, 8, vc(15), vc(1), 0, 0, 1, 0, (void *) "2", NULL, NULL },
12455 { jwin_check_proc, 84, 112, 168, 8, vc(15), vc(1), 0, 0, 1, 0, (void *) "3", NULL, NULL },
12456 { jwin_check_proc, 108, 112, 168, 8, vc(15), vc(1), 0, 0, 1, 0, (void *) "4", NULL, NULL },
12457 { jwin_check_proc, 132, 112, 168, 8, vc(15), vc(1), 0, 0, 1, 0, (void *) "5", NULL, NULL },
12458 { jwin_check_proc, 156, 112, 168, 8, vc(15), vc(1), 0, 0, 1, 0, (void *) "6", NULL, NULL },
12459 { jwin_check_proc, 12, 128, 168, 8, vc(15), vc(1), 0, 0, 1, 0, (void *) "7", NULL, NULL },
12460 { jwin_check_proc, 36, 128, 168, 8, vc(15), vc(1), 0, 0, 1, 0, (void *) "8", NULL, NULL },
12461 { jwin_check_proc, 60, 128, 168, 8, vc(15), vc(1), 0, 0, 1, 0, (void *) "9", NULL, NULL },
12462 { jwin_check_proc, 84, 128, 168, 8, vc(15), vc(1), 0, 0, 1, 0, (void *) "10", NULL, NULL },
12463 { jwin_check_proc, 108, 128, 168, 8, vc(15), vc(1), 0, 0, 1, 0, (void *) "11", NULL, NULL },
12464 { jwin_check_proc, 132, 128, 168, 8, vc(15), vc(1), 0, 0, 1, 0, (void *) "12", NULL, NULL },
12465 { jwin_check_proc, 156, 128, 168, 8, vc(15), vc(1), 0, 0, 1, 0, (void *) "13", NULL, NULL },
12466
12467 // 20
12468 { jwin_check_proc, 12, 144, 168, 8, vc(15), vc(1), 0, 0, 1, 0, (void *) "Ignore blank tiles", NULL, NULL },
12469 { jwin_func_button_proc, 14, 160, 60, 20, vc(14), vc(1), 0, 0, 0, 0, (void *) "Reset", NULL, (void*)massRecolorReset4Bit },
12470 { jwin_button_proc, 82, 160, 120, 20, vc(14), vc(1), 0, D_EXIT, 0, 0, (void *) "Switch to 8-bit mode", NULL, NULL },
12471 { jwin_button_proc, 44, 188, 60, 20, vc(14), vc(1), 0, D_EXIT, 0, 0, (void *) "OK", NULL, NULL },
12472 { jwin_button_proc, 112, 188, 60, 20, vc(14), vc(1), 0, D_EXIT, 0, 0, (void *) "Cancel", NULL, NULL },
12473
12474 { NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }
12475 };
12476
12477 #define MR4_SRC_COLORS 2
12478 #define MR4_DEST_COLORS 4
12479 #define MR4_8BIT_EFFECT_START 6
12480 #define MR4_IGNORE_BLANK 20
12481 #define MR4_RESET 21
12482 #define MR4_SWITCH 22
12483 #define MR4_OK 23
12484 #define MR4_CANCEL 24
12485
12486 static DIALOG recolor_8bit_dlg[] =
12487 {
12488 // (dialog proc) (x) (y) (w) (h) (fg) (bg) (key) (flags) (d1) (d2) (dp)
12489 { jwin_win_proc, 0, 0, 288, 224, 0, 0, 0, D_EXIT, 0, 0, (void *) "Recolor setup", NULL, NULL },
12490
12491 // 1
12492 { jwin_text_proc, 12, 32, 176, 8, vc(15), vc(1), 0, 0, 0, 0, (void *) "From", NULL, NULL },
12493 { d_mr_cset_proc, 10, 42, 132, 12, 0, 0, 0, D_SETTABLE, 0, 0, (void *)massRecolorSrc8Bit, NULL, NULL },
12494 { jwin_text_proc, 12, 60, 176, 8, vc(15), vc(1), 0, 0, 0, 0, (void *) "To", NULL, NULL },
12495 { d_mr_cset_proc, 10, 70, 132, 12, 0, 0, 0, D_SETTABLE, 0, 0, (void *)massRecolorDest8Bit, NULL, NULL },
12496 { d_mr_palette_proc, 144, 32, 132, 150, vc(15), vc(1), 0, 0, 0, 0, (void *) NULL, NULL, NULL },
12497
12498 // 6
12499 { jwin_check_proc, 12, 144, 168, 8, vc(15), vc(1), 0, 0, 1, 0, (void *) "Ignore blank tiles", NULL, NULL },
12500 { jwin_func_button_proc, 50, 160, 60, 20, vc(14), vc(1), 0, 0, 0, 0, (void *) "Reset", NULL, (void*)massRecolorReset8Bit },
12501 { jwin_button_proc, 118, 160, 120, 20, vc(14), vc(1), 0, D_EXIT, 0, 0, (void *) "Switch to 4-bit mode", NULL, NULL },
12502 { jwin_button_proc, 80, 188, 60, 20, vc(14), vc(1), 0, D_EXIT, 0, 0, (void *) "OK", NULL, NULL },
12503 { jwin_button_proc, 148, 188, 60, 20, vc(14), vc(1), 0, D_EXIT, 0, 0, (void *) "Cancel", NULL, NULL },
12504
12505 { NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }
12506 };
12507
12508 #define MR8_SRC_COLORS 2
12509 #define MR8_DEST_COLORS 4
12510 #define MR8_PALETTE 5
12511 #define MR8_IGNORE_BLANK 6
12512 #define MR8_RESET 7
12513 #define MR8_SWITCH 8
12514 #define MR8_OK 9
12515 #define MR8_CANCEL 10
12516
12517 static void massRecolorInit(int32_t cset)
12518 {
12519 massRecolorDraggedColor=-1;
12520 massRecolorCSet=cset;
12521
12522 recolor_4bit_dlg[0].dp2=get_zc_font(font_lfont);
12523 recolor_8bit_dlg[0].dp2=get_zc_font(font_lfont);
12524
12525 for(int32_t i=0; i<=13; i++)
12526 {
12527 if((massRecolor8BitCSets&(1<<i))!=0)
12528 recolor_4bit_dlg[MR4_8BIT_EFFECT_START+i].flags|=D_SELECTED;
12529 else
12530 recolor_4bit_dlg[MR4_8BIT_EFFECT_START+i].flags&=~D_SELECTED;
12531 }
12532
12533 if(massRecolorIgnoreBlank)
12534 {
12535 recolor_4bit_dlg[MR4_IGNORE_BLANK].flags|=D_SELECTED;
12536 recolor_8bit_dlg[MR8_IGNORE_BLANK].flags|=D_SELECTED;
12537 }
12538 else
12539 {
12540 recolor_4bit_dlg[MR4_IGNORE_BLANK].flags&=~D_SELECTED;
12541 recolor_8bit_dlg[MR8_IGNORE_BLANK].flags&=~D_SELECTED;
12542 }
12543
12544 large_dialog(recolor_4bit_dlg);
12545 large_dialog(recolor_8bit_dlg);
12546
12547 // Quick fix for large_dialog() screwing these up. It's ugly. Whatever.
12548 if((recolor_4bit_dlg[MR4_DEST_COLORS].w-4)%4!=0)
12549 {
12550 recolor_4bit_dlg[MR4_SRC_COLORS].x++;
12551 recolor_4bit_dlg[MR4_SRC_COLORS].w-=2;
12552 recolor_4bit_dlg[MR4_DEST_COLORS].x++;
12553 recolor_4bit_dlg[MR4_DEST_COLORS].w-=2;
12554
12555 recolor_8bit_dlg[MR8_SRC_COLORS].x++;
12556 recolor_8bit_dlg[MR8_SRC_COLORS].w-=2;
12557 recolor_8bit_dlg[MR8_DEST_COLORS].x++;
12558 recolor_8bit_dlg[MR8_DEST_COLORS].w-=2;
12559 recolor_8bit_dlg[MR8_PALETTE].x++;
12560 recolor_8bit_dlg[MR8_PALETTE].w-=2;
12561 recolor_8bit_dlg[MR8_PALETTE].y++;
12562 recolor_8bit_dlg[MR8_PALETTE].h-=2;
12563 }
12564 }
12565
12566 static void massRecolorApplyChanges()
12567 {
12568 massRecolor8BitCSets=0;
12569 for(int32_t i=0; i<=13; i++)
12570 {
12571 if((recolor_4bit_dlg[MR4_8BIT_EFFECT_START+i].flags&D_SELECTED)!=0)
12572 massRecolor8BitCSets|=1<<i;
12573 }
12574
12575 if(massRecolorType==MR_4BIT)
12576 massRecolorIgnoreBlank=(recolor_4bit_dlg[MR4_IGNORE_BLANK].flags&D_SELECTED)!=0;
12577 else
12578 massRecolorIgnoreBlank=(recolor_8bit_dlg[MR8_IGNORE_BLANK].flags&D_SELECTED)!=0;
12579 }
12580
12581 static bool massRecolorSetup(int32_t cset)
12582 {
12583 massRecolorInit(cset);
12584
12585 // Remember the current colors in case the user cancels.
12586 int32_t oldDest4Bit[16], oldSrc8Bit[16], oldDest8Bit[16];
12587 for(int32_t i=0; i<16; i++)
12588 {
12589 oldDest4Bit[i]=massRecolorDest4Bit[i];
12590 oldSrc8Bit[i]=massRecolorSrc8Bit[i];
12591 oldDest8Bit[i]=massRecolorDest8Bit[i];
12592 }
12593
12594 byte type=massRecolorType;
12595 int32_t ret;
12596 do
12597 {
12598 HANDLE_CLOSE_ZQDLG();
12599 if(exiting_program) break;
12600 if(type==MR_4BIT)
12601 {
12602 ret=do_zqdialog(recolor_4bit_dlg, MR4_OK);
12603 if(ret==MR4_SWITCH)
12604 type=MR_8BIT;
12605 }
12606 else
12607 {
12608 ret=do_zqdialog(recolor_8bit_dlg, MR8_OK);
12609 if(ret==MR8_SWITCH)
12610 type=MR_4BIT;
12611 }
12612 } while(ret==MR4_SWITCH || ret==MR8_SWITCH);
12613
12614 if(ret!=MR4_OK && ret!=MR8_OK) // Canceled
12615 {
12616 for(int32_t i=0; i<16; i++)
12617 {
12618 massRecolorDest4Bit[i]=oldDest4Bit[i];
12619 massRecolorSrc8Bit[i]=oldSrc8Bit[i];
12620 massRecolorDest8Bit[i]=oldDest8Bit[i];
12621 }
12622 return false;
12623 }
12624
12625 // OK
12626 massRecolorType=type;
12627 massRecolorApplyChanges();
12628 return true;
12629 }
12630
12631 static void massRecolorApply4Bit(int32_t tile)
12632 {
12633 byte buf[256];
12634 unpack_tile(newtilebuf, tile, 0, true);
12635
12636 if(newtilebuf[tile].format==tf4Bit)
12637 {
12638 for(int32_t i=0; i<256; i++)
12639 buf[i]=massRecolorDest4Bit[unpackbuf[i]];
12640 }
12641 else // 8-bit
12642 {
12643 for(int32_t i=0; i<256; i++)
12644 {
12645 word cset=unpackbuf[i]>>4;
12646 if((massRecolor8BitCSets&(1<<cset))!=0) // Recolor this CSet?
12647 {
12648 word color=unpackbuf[i]&15;
12649 buf[i]=(cset<<4)|massRecolorDest4Bit[color];
12650 }
12651 else
12652 buf[i]=unpackbuf[i];
12653 }
12654 }
12655
12656 pack_tile(newtilebuf, buf, tile);
12657 }
12658
12659 static void massRecolorApply8Bit(int32_t tile)
12660 {
12661 byte buf[256];
12662 unpack_tile(newtilebuf, tile, 0, true);
12663
12664 for(int32_t i=0; i<256; i++)
12665 {
12666 byte color=unpackbuf[i];
12667 for(int32_t j=0; j<16; j++)
12668 {
12669 if(massRecolorSrc8Bit[j]==color)
12670 {
12671 color=massRecolorDest8Bit[j];
12672 break;
12673 }
12674 }
12675 buf[i]=color;
12676 }
12677
12678 pack_tile(newtilebuf, buf, tile);
12679 }
12680
12681 static void massRecolorApply(int32_t tile)
12682 {
12683 if(massRecolorIgnoreBlank && blank_tile_table[tile])
12684 return;
12685
12686 if(massRecolorType==MR_4BIT)
12687 massRecolorApply4Bit(tile);
12688 else // 8-bit
12689 {
12690 if(newtilebuf[tile].format==tf4Bit)
12691 return;
12692 massRecolorApply8Bit(tile);
12693 }
12694 }
12695
12696 static void massRecolorReset4Bit()
12697 {
12698 for(int32_t i=0; i<16; i++)
12699 massRecolorDest4Bit[i]=i;
12700 recolor_4bit_dlg[MR4_DEST_COLORS].flags|=D_DIRTY;
12701 }
12702
12703 static void massRecolorReset8Bit()
12704 {
12705 for(int32_t i=0; i<16; i++)
12706 {
12707 massRecolorSrc8Bit[i]=0;
12708 massRecolorDest8Bit[i]=0;
12709 }
12710
12711 recolor_8bit_dlg[MR8_SRC_COLORS].flags|=D_DIRTY;
12712 recolor_8bit_dlg[MR8_DEST_COLORS].flags|=D_DIRTY;
12713 }
12714
12715 6 void center_zq_tiles_dialogs()
12716 {
12717 6 jwin_center_dialog(create_relational_tiles_dlg);
12718 6 jwin_center_dialog(icon_dlg);
12719 6 jwin_center_dialog(leech_dlg);
12720 6 jwin_center_dialog(move_textbox_list_dlg);
12721 6 jwin_center_dialog(recolor_4bit_dlg);
12722 6 jwin_center_dialog(recolor_8bit_dlg);
12723 6 }
12724
12725 //.ZCOMBO
12726
12727 int32_t readcombo_loop(PACKFILE* f, word section_version, newcombo& temp_combo);
12728 int32_t writecombo_loop(PACKFILE *f, word section_version, newcombo const& tmp_cmb);
12729
12730 int32_t readcombofile_old(PACKFILE *f, int32_t skip, byte nooverwrite, int32_t zversion,
12731 dword section_version, dword section_cversion, int32_t index, int32_t count)
12732 {
12733 newcombo temp_combo;
12734 for ( int32_t tilect = 0; tilect < count; tilect++ )
12735 {
12736 temp_combo.clear();
12737 if(!p_igetw(&temp_combo.tile,f))
12738 {
12739 return 0;
12740 }
12741 temp_combo.o_tile = temp_combo.tile;
12742
12743 if(!p_getc(&temp_combo.flip,f))
12744 {
12745 return 0;
12746 }
12747
12748 if(!p_getc(&temp_combo.walk,f))
12749 {
12750 return 0;
12751 }
12752
12753 if(!p_getc(&temp_combo.type,f))
12754 {
12755 return 0;
12756 }
12757
12758 if(!p_getc(&temp_combo.csets,f))
12759 {
12760 return 0;
12761 }
12762
12763 if(!p_getc(&temp_combo.frames,f))
12764 {
12765 return 0;
12766 }
12767
12768 if(!p_getc(&temp_combo.speed,f))
12769 {
12770 return 0;
12771 }
12772
12773 if(!p_igetw(&temp_combo.nextcombo,f))
12774 {
12775 return 0;
12776 }
12777
12778 if(!p_getc(&temp_combo.nextcset,f))
12779 {
12780 return 0;
12781 }
12782
12783 if(!p_getc(&temp_combo.flag,f))
12784 {
12785 return 0;
12786 }
12787
12788 if(!p_getc(&temp_combo.skipanim,f))
12789 {
12790 return 0;
12791 }
12792
12793 if(!p_igetw(&temp_combo.nexttimer,f))
12794 {
12795 return 0;
12796 }
12797
12798 if(!p_getc(&temp_combo.skipanimy,f))
12799 {
12800 return 0;
12801 }
12802
12803 if(!p_getc(&temp_combo.animflags,f))
12804 {
12805 return 0;
12806 }
12807
12808 //2.55 starts here
12809 if ( zversion >= 0x255 )
12810 {
12811 if ( section_version >= 12 )
12812 {
12813 for ( int32_t q = 0; q < NUM_COMBO_ATTRIBUTES; q++ )
12814 {
12815 if(!p_igetl(&temp_combo.attributes[q],f))
12816 {
12817 return 0;
12818 }
12819 }
12820 if(!p_igetl(&temp_combo.usrflags,f))
12821 {
12822 return 0;
12823 }
12824 for ( int32_t q = 0; q < 3; q++ )
12825 {
12826 if(!p_igetl(&temp_combo.triggerflags[q],f))
12827 {
12828 return 0;
12829 }
12830 }
12831
12832 if(!p_igetl(&temp_combo.triggerlevel,f))
12833 {
12834 return 0;
12835 }
12836 if(section_version >= 22)
12837 {
12838 if(!p_getc(&temp_combo.triggerbtn,f))
12839 {
12840 return 0;
12841 }
12842 }
12843 if(section_version < 23)
12844 {
12845 switch(temp_combo.type) //combotriggerCMBTYPEFX now required for combotype-specific effects
12846 {
12847 case cSCRIPT1: case cSCRIPT2: case cSCRIPT3: case cSCRIPT4: case cSCRIPT5:
12848 case cSCRIPT6: case cSCRIPT7: case cSCRIPT8: case cSCRIPT9: case cSCRIPT10:
12849 case cTRIGGERGENERIC: case cCSWITCH:
12850 temp_combo.triggerflags[0] |= combotriggerCMBTYPEFX;
12851 }
12852 }
12853 if(section_version >= 24)
12854 {
12855 if(!p_getc(&temp_combo.triggeritem,f))
12856 {
12857 return 0;
12858 }
12859 if(!p_getc(&temp_combo.trigtimer,f))
12860 {
12861 return 0;
12862 }
12863 }
12864 if(section_version >= 25)
12865 {
12866 if(!p_getc(&temp_combo.trigsfx,f))
12867 {
12868 return 0;
12869 }
12870 }
12871 else
12872 {
12873 switch(temp_combo.type)
12874 {
12875 case cLOCKBLOCK: case cBOSSLOCKBLOCK:
12876 if(!(temp_combo.usrflags & cflag3))
12877 temp_combo.attribytes[3] = WAV_DOOR;
12878 temp_combo.usrflags &= ~cflag3;
12879 break;
12880 }
12881 }
12882 if(section_version < 26)
12883 {
12884 if(temp_combo.type == cARMOS)
12885 {
12886 if(temp_combo.usrflags & cflag1)
12887 temp_combo.usrflags |= cflag3;
12888 }
12889 }
12890 if(section_version >= 27)
12891 {
12892 if(!p_igetl(&temp_combo.trigchange,f))
12893 {
12894 return qe_invalid;
12895 }
12896 }
12897 else
12898 {
12899 if(temp_combo.triggerflags[0] & 0x00040000) //'next'
12900 temp_combo.trigchange = 1;
12901 else if(temp_combo.triggerflags[0] & 0x00080000) //'prev'
12902 temp_combo.trigchange = -1;
12903 else temp_combo.trigchange = 0;
12904 temp_combo.triggerflags[0] &= ~(0x00040000|0x00080000);
12905 }
12906 if(section_version >= 29)
12907 {
12908 if(!p_igetw(&temp_combo.trigprox,f))
12909 {
12910 return qe_invalid;
12911 }
12912 if(!p_getc(&temp_combo.trigctr,f))
12913 {
12914 return qe_invalid;
12915 }
12916 if(!p_igetl(&temp_combo.trigctramnt,f))
12917 {
12918 return qe_invalid;
12919 }
12920 }
12921 else
12922 {
12923 temp_combo.trigprox = 0;
12924 temp_combo.trigctr = 0;
12925 temp_combo.trigctramnt = 0;
12926 }
12927 if(section_version >= 30)
12928 {
12929 if(!p_getc(&temp_combo.triglbeam,f))
12930 {
12931 return qe_invalid;
12932 }
12933 }
12934 else temp_combo.triglbeam = 0;
12935 if(section_version >= 31)
12936 {
12937 if(!p_getc(&temp_combo.trigcschange,f))
12938 {
12939 return qe_invalid;
12940 }
12941 if(!p_igetw(&temp_combo.spawnitem,f))
12942 {
12943 return qe_invalid;
12944 }
12945 if(!p_igetw(&temp_combo.spawnenemy,f))
12946 {
12947 return qe_invalid;
12948 }
12949 if(!p_getc(&temp_combo.exstate,f))
12950 {
12951 return qe_invalid;
12952 }
12953 if(!p_igetl(&temp_combo.spawnip,f))
12954 {
12955 return qe_invalid;
12956 }
12957 if(!p_getc(&temp_combo.trigcopycat,f))
12958 {
12959 return qe_invalid;
12960 }
12961 }
12962 else
12963 {
12964 temp_combo.trigcschange = 0;
12965 temp_combo.spawnitem = 0;
12966 temp_combo.spawnenemy = 0;
12967 temp_combo.exstate = -1;
12968 temp_combo.spawnip = 0;
12969 temp_combo.trigcopycat = 0;
12970 }
12971 if(section_version >= 32)
12972 {
12973 if(!p_getc(&temp_combo.trigcooldown,f))
12974 {
12975 return qe_invalid;
12976 }
12977 }
12978 else
12979 {
12980 temp_combo.trigcooldown = 0;
12981 }
12982 char label[12];
12983 label[11] = '\0';
12984 for ( int32_t q = 0; q < 11; q++ )
12985 {
12986 if(!p_getc(&label[q],f))
12987 {
12988 return 0;
12989 }
12990 }
12991 temp_combo.label = label;
12992 }
12993 if ( section_version >= 13 )
12994 {
12995 for ( int32_t q = 0; q < NUM_COMBO_ATTRIBUTES; q++ )
12996 {
12997 if(!p_getc(&temp_combo.attribytes[q],f))
12998 {
12999 return 0;
13000 }
13001 }
13002
13003 }
13004 }
13005
13006 if ( !(skip && (index+(tilect-1)) < skip) ) //is -1 still needed here?
13007 {
13008 if ( !nooverwrite || combobuf[index+tilect].is_blank() )
13009 {
13010 combobuf[index+(tilect)] = temp_combo;
13011 }
13012 }
13013 }
13014
13015 return 1;
13016 }
13017
13018 int32_t readcombofile(PACKFILE *f, int32_t skip, byte nooverwrite, int32_t start)
13019 {
13020 dword section_version=0;
13021 dword section_cversion=0;
13022 int32_t zversion = 0;
13023 int32_t zbuild = 0;
13024
13025 if(!p_igetl(&zversion,f))
13026 {
13027 return 0;
13028 }
13029 if(!p_igetl(&zbuild,f))
13030 {
13031 return 0;
13032 }
13033 if(!p_igetw(&section_version,f))
13034 {
13035 return 0;
13036 }
13037 if(!p_igetw(&section_cversion,f))
13038 {
13039 return 0;
13040 }
13041
13042 if ( zversion > ZELDA_VERSION )
13043 {
13044 al_trace("Cannot read .zcombo packfile made in ZC version (%x) in this version of ZC (%x)\n", zversion, ZELDA_VERSION);
13045 return 0;
13046 }
13047
13048 else if ( ( section_version > V_COMBOS ) || ( section_version == V_COMBOS && section_cversion > CV_COMBOS ) )
13049 {
13050 al_trace("Cannot read .zcombo packfile made using V_COMBOS (%d) subversion (%d)\n", section_version, section_cversion);
13051 return 0;
13052
13053 }
13054 else
13055 {
13056 al_trace("Reading a .zcombo packfile made in ZC Version: %x, Build: %d\n", zversion, zbuild);
13057 }
13058
13059 int32_t index = 0;
13060 int32_t count = 0;
13061
13062 //tile id
13063 if(!p_igetl(&index,f))
13064 {
13065 return 0;
13066 }
13067 if(start > -1) index = start;
13068 // al_trace("Reading combo: index(%d)\n", index);
13069
13070 //tile count
13071 if(!p_igetl(&count,f))
13072 {
13073 return 0;
13074 }
13075 // al_trace("Reading combo: count(%d)\n", count);
13076 reset_combo_animations();
13077 reset_combo_animations2();
13078
13079 if(section_version < 33)
13080 return readcombofile_old(f,skip,nooverwrite,zversion,section_version,section_cversion,index,count);
13081
13082 newcombo temp_combo;
13083 size_t end = index+count;
13084 for ( size_t q = index; q < end; q++ )
13085 {
13086 auto ret = readcombo_loop(f,section_version,temp_combo);
13087 if(ret) return 0;
13088
13089 if ( !(skip && q-1 < skip) )
13090 {
13091 if ( !nooverwrite || combobuf[q].is_blank() )
13092 {
13093 combobuf[q] = temp_combo;
13094 }
13095 }
13096 }
13097
13098 return 1;
13099 }
13100 int32_t readcombofile_to_location(PACKFILE *f, int32_t start, byte nooverwrite, int32_t skip)
13101 {
13102 return readcombofile(f,skip,nooverwrite,start);
13103 }
13104 int32_t writecombofile(PACKFILE *f, int32_t index, int32_t count)
13105 {
13106 dword section_version=V_COMBOS;
13107 dword section_cversion=CV_COMBOS;
13108 int32_t zversion = ZELDA_VERSION;
13109 int32_t zbuild = VERSION_BUILD;
13110
13111 if(!p_iputl(zversion,f))
13112 {
13113 return 0;
13114 }
13115 if(!p_iputl(zbuild,f))
13116 {
13117 return 0;
13118 }
13119 if(!p_iputw(section_version,f))
13120 {
13121 return 0;
13122 }
13123
13124 if(!p_iputw(section_cversion,f))
13125 {
13126 return 0;
13127 }
13128
13129 //start tile id
13130 if(!p_iputl(index,f))
13131 {
13132 return 0;
13133 }
13134
13135 //count
13136 if(!p_iputl(count,f))
13137 {
13138 return 0;
13139 }
13140 reset_combo_animations();
13141 reset_combo_animations2();
13142 size_t end = index+count;
13143 for(size_t q = index; q < end; ++q)
13144 {
13145 if(writecombo_loop(f, section_version, combobuf[q]))
13146 return 0;
13147 }
13148
13149 return 1;
13150
13151 }
13152
13153 //.ZALIAS
13154
13155
13156 //.ZALIAS
13157
13158 int32_t readcomboaliasfile(PACKFILE *f)
13159 {
13160 dword section_version=0;
13161 dword section_cversion=0;
13162 int32_t zversion = 0;
13163 int32_t zbuild = 0;
13164 word tempword = 0;
13165
13166 if(!p_igetl(&zversion,f))
13167 {
13168 return 0;
13169 }
13170 if(!p_igetl(&zbuild,f))
13171 {
13172 return 0;
13173 }
13174 if(!p_igetw(&section_version,f))
13175 {
13176 return 0;
13177 }
13178 if(!p_igetw(&section_cversion,f))
13179 {
13180 return 0;
13181 }
13182 al_trace("readoneweapon section_version: %d\n", section_version);
13183 al_trace("readoneweapon section_cversion: %d\n", section_cversion);
13184
13185 if ( zversion > ZELDA_VERSION )
13186 {
13187 al_trace("Cannot read .zalias packfile made in ZC version (%x) in this version of ZC (%x)\n", zversion, ZELDA_VERSION);
13188 return 0;
13189 }
13190
13191 else if ( ( section_version > V_COMBOALIASES ) || ( section_version == V_COMBOALIASES && section_cversion > CV_COMBOALIASES ) )
13192 {
13193 al_trace("Cannot read .zalias packfile made using V_COMBOALIASES (%d) subversion (%d)\n", section_version, section_cversion);
13194 return 0;
13195
13196 }
13197 else
13198 {
13199 al_trace("Reading a .zalias packfile made in ZC Version: %x, Build: %d\n", zversion, zbuild);
13200 }
13201
13202 int32_t index = 0;
13203 int32_t count = 0;
13204 int32_t count2 = 0;
13205 byte tempcset = 0;
13206
13207 //tile id
13208 if(!p_igetl(&index,f))
13209 {
13210 return 0;
13211 }
13212 al_trace("Reading combo: index(%d)\n", index);
13213
13214 //tile count
13215 if(!p_igetl(&count,f))
13216 {
13217 return 0;
13218 }
13219 al_trace("Reading combo: count(%d)\n", count);
13220
13221 combo_alias temp_alias;
13222 memset(&temp_alias, 0, sizeof(temp_alias));
13223
13224 for ( int32_t tilect = 0; tilect < count; tilect++ )
13225 {
13226 memset(&temp_alias, 0, sizeof(temp_alias));
13227 if(!p_igetw(&temp_alias.combo,f))
13228 {
13229 return 0;
13230 }
13231
13232 if(!p_getc(&temp_alias.cset,f))
13233 {
13234 return 0;
13235 }
13236
13237
13238
13239 if(!p_igetl(&count2,f))
13240 {
13241 return 0;
13242 }
13243 al_trace("Read, Combo alias count is: %d\n", count2);
13244 if(!p_getc(&temp_alias.width,f))
13245 {
13246 return 0;
13247 }
13248
13249 if(!p_getc(&temp_alias.height,f))
13250 {
13251 return 0;
13252 }
13253
13254 if(!p_getc(&temp_alias.layermask,f))
13255 {
13256 return 0;
13257 }
13258 //These values are flexible, and may differ in size, so we delete them
13259 //and recreate them at the correct size on the pointer.
13260 temp_alias.combos.clear();
13261 temp_alias.csets.clear();
13262 for(int32_t k=0; k<count2; k++)
13263 {
13264 if(!p_igetw(&tempword,f))
13265 {
13266 return 0;
13267 }
13268 else
13269 {
13270
13271
13272 temp_alias.combos[k] = tempword;
13273 }
13274 }
13275
13276 for(int32_t k=0; k<count2; k++)
13277 {
13278 if(!p_getc(&tempcset,f))
13279 //if(!p_getc(&temp_alias.csets[k],f))
13280 {
13281 return 0;
13282 }
13283 else
13284 {
13285
13286 temp_alias.csets[k] = tempcset;
13287 }
13288 }
13289 memcpy(&combo_aliases[index+(tilect)],&temp_alias,sizeof(combo_alias));
13290 }
13291
13292 //::memcpy(&(newtilebuf[tile_index]),&temptile,sizeof(tiledata));
13293
13294
13295 return 1;
13296
13297 }
13298
13299 int32_t readcomboaliasfile_to_location(PACKFILE *f, int32_t start)
13300 {
13301 dword section_version=0;
13302 dword section_cversion=0;
13303 int32_t zversion = 0;
13304 int32_t zbuild = 0;
13305
13306 if(!p_igetl(&zversion,f))
13307 {
13308 return 0;
13309 }
13310 if(!p_igetl(&zbuild,f))
13311 {
13312 return 0;
13313 }
13314 if(!p_igetw(&section_version,f))
13315 {
13316 return 0;
13317 }
13318 if(!p_igetw(&section_cversion,f))
13319 {
13320 return 0;
13321 }
13322 al_trace("readcomboaliasfile_to_location section_version: %d\n", section_version);
13323 al_trace("readcomboaliasfile_to_location section_cversion: %d\n", section_cversion);
13324
13325 if ( zversion > ZELDA_VERSION )
13326 {
13327 al_trace("Cannot read .zalias packfile made in ZC version (%x) in this version of ZC (%x)\n", zversion, ZELDA_VERSION);
13328 return 0;
13329 }
13330 else if ( ( section_version > V_COMBOALIASES ) || ( section_version == V_COMBOALIASES && section_cversion > CV_COMBOALIASES ) )
13331 {
13332 al_trace("Cannot read .zalias packfile made using V_COMBOALIASES (%d) subversion (%d)\n", section_version, section_cversion);
13333 return 0;
13334
13335 }
13336 else
13337 {
13338 al_trace("Reading a .zalias packfile made in ZC Version: %x, Build: %d\n", zversion, zbuild);
13339 }
13340
13341 int32_t index = 0;
13342 int32_t count = 0;
13343 int32_t count2 = 0;
13344 byte tempcset = 0;
13345 word tempword = 0;
13346
13347
13348 //tile id
13349 if(!p_igetl(&index,f))
13350 {
13351 return 0;
13352 }
13353 al_trace("Reading tile: index(%d)\n", index);
13354
13355 //tile count
13356 if(!p_igetl(&count,f))
13357 {
13358 return 0;
13359 }
13360 al_trace("Reading tile: count(%d)\n", count);
13361
13362
13363 combo_alias temp_alias;
13364 memset(&temp_alias, 0, sizeof(temp_alias));
13365
13366 for ( int32_t tilect = 0; tilect < count; tilect++ )
13367 {
13368 memset(&temp_alias, 0, sizeof(temp_alias));
13369 if(!p_igetw(&temp_alias.combo,f))
13370 {
13371 return 0;
13372 }
13373
13374 if(!p_getc(&temp_alias.cset,f))
13375 {
13376 return 0;
13377 }
13378
13379 int32_t count2 = 0;
13380
13381 if(!p_igetl(&count2,f))
13382 {
13383 return 0;
13384 }
13385
13386 if(!p_getc(&temp_alias.width,f))
13387 {
13388 return 0;
13389 }
13390
13391 if(!p_getc(&temp_alias.height,f))
13392 {
13393 return 0;
13394 }
13395
13396 if(!p_getc(&temp_alias.layermask,f))
13397 {
13398 return 0;
13399 }
13400 //These values are flexible, and may differ in size, so we delete them
13401 //and recreate them at the correct size on the pointer.
13402 temp_alias.combos.clear();
13403 temp_alias.csets.clear();
13404
13405 for(int32_t k=0; k<count2; k++)
13406 {
13407 if(!p_igetw(&tempword,f))
13408 {
13409 return 0;
13410 }
13411 else
13412 {
13413 temp_alias.combos[k] = tempword;
13414 }
13415 }
13416
13417 for(int32_t k=0; k<count2; k++)
13418 {
13419 if(!p_getc(&tempcset,f))
13420 {
13421 return 0;
13422 }
13423 else
13424 {
13425 temp_alias.csets[k] = tempcset;
13426 }
13427 }
13428
13429 if ( start+(tilect) < MAXCOMBOALIASES )
13430 {
13431 memcpy(&combo_aliases[start+(tilect)],&temp_alias,sizeof(temp_alias));
13432 }
13433 }
13434 return 1;
13435 }
13436 int32_t writecomboaliasfile(PACKFILE *f, int32_t index, int32_t count)
13437 {
13438 al_trace("Running writecomboaliasfile\n");
13439 dword section_version=V_COMBOALIASES;
13440 dword section_cversion=CV_COMBOALIASES;
13441 int32_t zversion = ZELDA_VERSION;
13442 int32_t zbuild = VERSION_BUILD;
13443
13444 if(!p_iputl(zversion,f))
13445 {
13446 return 0;
13447 }
13448 if(!p_iputl(zbuild,f))
13449 {
13450 return 0;
13451 }
13452 if(!p_iputw(section_version,f))
13453 {
13454 return 0;
13455 }
13456
13457 if(!p_iputw(section_cversion,f))
13458 {
13459 return 0;
13460 }
13461
13462 //start tile id
13463 if(!p_iputl(index,f))
13464 {
13465 return 0;
13466 }
13467
13468 //count
13469 if(!p_iputl(count,f))
13470 {
13471 return 0;
13472 }
13473
13474 for ( int32_t tilect = 0; tilect < count; tilect++ )
13475 {
13476
13477 if(!p_iputw(combo_aliases[index+(tilect)].combo,f))
13478 {
13479 return 0;
13480 }
13481
13482 if(!p_putc(combo_aliases[index+(tilect)].cset,f))
13483 {
13484 return 0;
13485 }
13486
13487 int32_t count2 = ((combo_aliases[index+(tilect)].width+1)*(combo_aliases[index+(tilect)].height+1))*(comboa_lmasktotal(combo_aliases[index+(tilect)].layermask)+1);
13488
13489 if(!p_iputl(count2,f))
13490 {
13491 return 0;
13492 }
13493 al_trace("Write`, Combo alias count is: %d\n", count2);
13494
13495 if(!p_putc(combo_aliases[index+(tilect)].width,f))
13496 {
13497 return 0;
13498 }
13499
13500 if(!p_putc(combo_aliases[index+(tilect)].height,f))
13501 {
13502 return 0;
13503 }
13504
13505 if(!p_putc(combo_aliases[index+(tilect)].layermask,f))
13506 {
13507 return 0;
13508 }
13509
13510 for(int32_t k=0; k<count2; k++)
13511 {
13512 if(!p_iputw(combo_aliases[index+(tilect)].combos[k],f))
13513 {
13514 return 0;
13515 }
13516 }
13517
13518 for(int32_t k=0; k<count2; k++)
13519 {
13520 if(!p_putc(combo_aliases[index+(tilect)].csets[k],f))
13521 {
13522 return 0;
13523 }
13524 }
13525 }
13526
13527 return 1;
13528
13529 }
13530